Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

欢迎使用 Dora-rs

Dora 是一个用于构建响应式数据流应用的轻量级框架,专为机器人、边缘计算和实时系统设计。

为什么选择 Dora?

  • 模块化:通过 Operator 组合复杂流水线
  • 低延迟:Rust 核心 + 零拷贝通信
  • 多语言:Rust 与 Python 节点无缝协作
  • 轻量部署:无中心调度器,单二进制即可运行

快速体验(需 Rust)

cargo install dora-cli
dora new hello-dora && cd hello-dora
dora run

项目文档

教程

欢迎来到 DORA-RS 实践教程!本教程将帮助你从零开始学习如何使用 DORA 构建机器人应用。

概述

DORA (Dataflow-Oriented Robotic Architecture) 是一个现代化的机器人框架,提供:

  • 模块化设计 - 将复杂系统拆分为独立节点
  • 低延迟通信 - 基于共享内存和零拷贝传输
  • 多语言支持 - Python、Rust、C/C++ 混合编程
  • 轻量级部署 - 无需复杂的依赖配置

学习路径

新手入门

如果你是 DORA 新手,建议按以下顺序学习:

  1. 安装 - 安装 DORA CLI 和依赖
  2. echo 示例 - 了解基本的数据流概念
  3. Python 数据流 - 创建你的第一个 Python 节点
  4. 使用相机 - 学习处理视频流

多语言开发

根据你熟悉的编程语言选择:

AI 与感知

对 AI 应用感兴趣?推荐学习:

机器人控制

需要控制真实机器人?查看:

源码仓库

所有示例的完整源码请访问:gitcode.com/dora-org/dora-examples

获取帮助

安装

Dora 提供了多种安装方式

pip install dora-rs-cli
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/dora-rs/dora/releases/latest/download/dora-cli-installer.sh | sh
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/dora-rs/dora/releases/latest/download/dora-cli-installer.sh | sh
powershell -ExecutionPolicy ByPass -c "irm https://github.com/dora-rs/dorareleases/latest/download/dora-cli-installer.ps1 | iex"
cargo install dora-cli
docker pull ghcr.io/dora-rs/dora-slim #拉取镜像
docker run ghcr.io/dora-rs/dora-slim dora --help #运行容器
git clone https://github.com/dora-rs/dora.git
cd dora
cargo build --release -p dora-cli
PATH=$PATH:$(pwd)/target/release

Important

本文主要围绕主分支的最新代码展开,如果想获得完全相同体验请尽量使用主分支上的Dora。 所有的样例以及部分多编程语言涉及到的特定包(Rust Crates)只在源码中给出,现阶段推荐从源码安装

确认完成安装

$ dora --version
dora-cli 0.3.11

从源码安装dora(以Ubuntu24.04为例)

安装Rust

安装rustup,rustup是管理Rust版本、编译工具链的重要工具

$ sudo apt install curl -y # 安装curl,如果未安装
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # 弹出选项,回车选择默认安装即可
$ export PATH=$PATH:$HOME/.cargo/bin # 设置环境变量

rustup安装画面

获取Dora源代码

$ sudo apt install git -y # 安装git,如果未安装
$ git clone https://github.com/dora-rs/dora.git
$ cd dora

编译Dora-CLI

Dora-CLI是非常实用的命令行工具,它提供了许多方便的命令来管理Dora项目。

$ sudo apt install build-essential -y # 安装C/C++编译环境相关的包(包括g++等),如果未安装
$ cargo build --release --package dora-cli

添加到环境变量

$ export PATH=$PATH:$(pwd)/target/release # 添加到环境变量

或者可以选择官方提供的脚本

$ ./install.sh

DORA 机器人框架概述

DORA (Data Oriented Robot Architecture) 是一个新兴的机器人框架,其核心在于为基于人工智能的机器人应用提供低延迟高可组合性分布式数据流能力。

该框架的关键优势在于:

  • 基于 Rust 语言的底层架构
  • 对多种编程语言(包括 Python 和 C/C++)的支持
  • 高效的通信机制,如共享内存和 Zenoh 网络协议

社区参与度方面,DORA 在 GitHub 上获得了显著关注,并通过训练营等活动积极拓展用户群体。项目的发展趋势表明,DORA 正致力于提升其分布式能力、与 ROS2 的互操作性,并扩展其节点生态系统。


一、DORA 中间件介绍

1.1 核心概念与架构

节点 (Nodes)

节点是独立的、隔离的进程,通过 dora 库与其他节点通信。这种隔离的设计在安全性至上的应用场景中尤为重要,并且能够实现细粒度的资源管理,例如将 CPU 核心绑定到特定的自定义节点上。

💡 如果一个节点发生故障,这种隔离特性可以有效地防止整个系统崩溃。

操作器 (Operators)

操作器是轻量级的、协同的、基于库的组件,由 dora 运行时节点执行。操作器可以利用 dora 运行时提供的各种高级功能,例如:

  • 优先级调度
  • 原生截止时间支持

这种设计使得在同一台机器上运行数千个操作器成为可能,从而提高了资源利用率。

协调器 (Coordinator)

协调器负责从 YAML 文件中读取数据流配置,进行验证,并将节点和操作器部署到指定的或自动确定的机器上。协调器还具备以下功能:

功能描述
健康监控监控操作器的健康状态
自动缩放云节点的自动缩放能力
复制与重启操作器的复制与重启机制

协调器的这些功能表明 DORA 具备支持复杂、分布式机器人系统的能力,并为云端部署提供了可能性。

数据流模型

DORA 的应用被建模为有向图管道,这种数据流模型强调了中间件的可组合性。

  • 开发者能够轻松地交换和替换机器人应用中的组件
  • 提高了开发的灵活性和模块化程度
  • 有助于可视化和理解系统内的信息和控制流

数据流的配置采用 YAML 声明式编程。使用 YAML 进行配置简化了机器人应用的部署和管理,降低了用户的入门门槛。声明式配置允许开发者定义应用的期望状态,而无需指定执行步骤。


1.2 关键技术特性

⚡ 低延迟

DORA 非常注重低延迟通信,这主要得益于:

  • 使用 Rust 语言实现的核心(高性能特点)
  • 基于共享内存的发布/订阅 (PubSub) 机制

这种对低延迟的强调使得 DORA 非常适合需要实时数据处理和控制的机器人应用。

🔧 可组合性

可组合性是 DORA 的另一个关键特性:

  • 允许开发者创建包含多种编程语言组件的应用
  • 操作器和自定义节点可以被复用和隔离
  • 语言无关性和组件复用能力显著提高了开发效率

🌐 分布式能力

DORA 具备强大的分布式能力:

  • 通过集成 Zenoh 网络协议实现机器间通信
  • 利用 OpenTelemetry 进行分布式遥测

内置的分布式计算支持对于将机器人应用扩展到单个机器之外至关重要,从而能够支持跨多个机器人或云基础设施的复杂部署。

🌍 多语言支持

语言特点
Rust性能卓越,适合核心功能开发
Python易于使用,适合快速原型设计和 AI 集成
C/C++广泛应用于系统级编程和硬件接口

1.3 通信基础设施

本地通信:共享内存 + Apache Arrow

DORA 在单台机器内部使用共享内存Apache Arrow 数据格式来实现零拷贝消息传递

┌─────────────┐    零拷贝    ┌─────────────┐
│   节点 A     │ ──────────→ │   节点 B    │
│             │  共享内存    │             │
└─────────────┘             └─────────────┘

优势:

  • 显著降低系统开销和延迟
  • 最小化 CPU 使用率
  • 最大化数据吞吐量
  • 对实时处理传感器数据至关重要

机器间通信:Zenoh 协议

对于机器间的通信,DORA 集成了 Zenoh 协议,以实现鲁棒的网络通信:

  • 处理网络断连
  • 网络地址转换 (NAT) 穿透
  • 发布/订阅功能
  • 对网络问题的弹性

选择 Zenoh 作为通信层突显了 DORA 构建可靠且可扩展的分布式机器人系统的决心。

ROS2 桥接

⚠️ 注意: ROS2 桥接目前处于不稳定状态

DORA 提供了 ROS2 桥接功能:

  • 无编译消息传递:简化与 ROS2 生态系统的集成
  • 自动类型转换:ROS2 消息与 Arrow 数组之间的自动转换

ROS 拥有庞大的用户基础和丰富的软件包库。与 ROS2 的桥接使得 DORA 能够利用现有的生态系统并吸引熟悉 ROS 的开发者。

echo

Dora中,一个逻辑功能通常作为节点(Node)。不同逻辑功能的交互依赖于信息的交互(Dataflow)。为了方便不同节点之间的组合,Dora使用yaml文件来声明消息的“流动”。

yaml不仅声明了不同节点消息的输入、输出,还可以声明节点构建(编译、安装)的过程。在使用这些节点之前需要先进行构建。

构建

Tip

如果使用uv管理的python可在命令中加入--uv参数 进入examples/echo文件夹,执行命令

# Create a virtual environment if it doesn't exist
$ uv venv -p 3.11 --seed 
$ dora build dataflow.yml --uv
$ dora run dataflow.yml --uv

输出:

Using Python 3.11.12 environment at: ...
Resolved 4 packages in 1.20s
      Built pyarrow-sender @ ...
Prepared 1 package in 693ms
Installed 1 package in 1ms
 ~ pyarrow-sender==0.3.11 (...)
Using Python 3.11.12 environment at: ...
Resolved 4 packages in 4ms
      Built dora-echo @ ...
Prepared 1 package in 507ms
Installed 1 package in 1ms
 + dora-echo==0.3.11 (...)
Using Python 3.11.12 environment at: ...
Resolved 4 packages in 3ms
      Built pyarrow-assert @ ...
Prepared 1 package in 499ms
Installed 1 package in 1ms
 ~ pyarrow-assert==0.3.11 (...)

运行

依据yaml文件运行Dora框架:

$ dora run dataflow.yaml # --uv

输出:

... INFO run_inner: dora_daemon::log:     pyarrow-assert finished successfully...

各节点的作用

node-hub提供了很多现成的方便复用的节点

Dora中通过环境变量为节点提供参数

  • pyarrow-sender节点:生成了内容为DATA的信息
  • dora-echo节点:将输入的内容发送出去
  • pyarrow-assert节点:判断接收消息与DATA是否一致

额外的尝试

更改pyarrow-senderpyarrow-assertDATA参数,在二者不一致时运行会产生报错 输出:

... [ERROR]
Dataflow failed:

Node `pyarrow-assert` failed: exited with code 1 with stderr output: ...

源码

完整源码请参考:dora-examples/echo

多守护进程(Daemon)

Dora通过Coordinator来协调多个Daemon的运行。Daemon可以来自不同的机器。这是Dora分布式的基础。

启动准备

启动一个协调器(Coordinator)

$ dora coordinator

其运行ip与端口的绑定设置,可通过添加--help参数来查看,样例中用默认的设置即可。

启动守护进程(Daemon)

$ dora daemon --machine-id A
$ dora daemon --machine-id B

分别启动两个分别名为A和B的守护进程。 可以通过--coordinator-addr--coordinator-port来指定协调器的地址和端口。 具体可以参考dora daemon --help

构建

$ dora build dataflow.yml

可以通过--coordinator-addr--coordinator-port来指定协调器的地址和端口。 具体可以参考dora build --help

运行

$ dora start dataflow.yml

可以通过--coordinator-addr--coordinator-port来指定协调器的地址和端口。 具体可以参考dora start --help

源码

完整源码请参考:dora-examples/multiple-daemons

构建与加载

Dora-cli 中常用的命令

Dora命令行工具提供了buildstart等命令。

  • coordinator启动一个coordinator进程,用于调度协调。
  • daemon在本地启动一个daemon进程,用于运行dataflow,可以指定连接到任一coordinator。
  • start启动一份dataflow,可以指定连接到任一coordinator。
  • run相当于在本地自行创建一个coordinator、daemon并在其上加载对应的dataflow.yml。

YAML配置文件

Dora通过使用YAML配置文件来描述dataflow。 形如:

nodes:
    - id: rust-node
      _unstable_deploy:
          machine: A
      build: cargo build --release -p rust-dataflow-example-node
      path: $DORA_EXAMPLES/target/release/rust-dataflow-example-node
      inputs:
          tick: dora/timer/millis/10
      outputs:
          - random

    - id: rust-status-node
      _unstable_deploy:
          machine: A
      build: cargo build --release -p rust-dataflow-example-status-node
      path: $DORA_EXAMPLES/target/release/rust-dataflow-example-status-node
      inputs:
          tick: dora/timer/millis/100
          random: rust-node/random
      outputs:
          - status

    - id: rust-sink
      _unstable_deploy:
          machine: B
      build: cargo build --release -p rust-dataflow-example-sink
      path: $DORA_EXAMPLES/target/release/rust-dataflow-example-sink
      inputs:
          message: rust-status-node/status

通过环境变量更灵活的启动

在build和path字段中都可以使用环境变量,例如$DORA_EXAMPLES。 这使得节点的位置可以更加灵活的放置。 值得注意的是,这两个字段中的环境变量会使用daemon所处运行环境的环境变量。

构建字段的技巧

Dora的build字段参考了Github Action的设计,但是其功能并不完备。 build字段允许通过多行来声明需要多个命令的构建。 如果需要借助脚本或更复杂的参数时可以使用bash -c "..."

编程语言

Dora的核心部分及大部分功能虽然使用Rust编写,但是也为其它编程语言提供了可编程接口支持多种编程语言,包括Python、C++等。

在本节中将展示不同编程语言中Dora的使用。

C/C++

需要预先准备的包

为了实现C/C++多语言混合编程,需要准备好相关的包。 需要从源码安装Dora,并且构建相关包:

  • 运行时
$ cargo build -p dora-runtime # --release
  • 如果需要使用C API
$ cargo build -p dora-node-api-c # --release
$ cargo build -p dora-operator-api-c # --release
  • 如果需要使用Rust API
$ cargo build -p dora-node-api-cxx # --release
$ cargo build -p dora-operator-api-cxx # --release

当使用启用release编译时,需注意将连接的地址target/debug替换为target/release 如果对Rust与C++的混合编译感兴趣,可以参阅cxx.rs

C++ 样例

数据流

Dora相关包的准备

需要预先准备的包 官方样例中使用clang++进行编译,实测g++也是可以使用的,对于大部分的Linux发行版(如Ubuntu等)使用默认安装的g++即可。

C API

构建

alias CXX='clang++' # CXX='g++'
mkdir build

# 构建算子
CXX -c operator-c-api/operator.cc -std=c++17 -o operator-c-api/operator.o -fPIC
CXX -shared operator-c-api/operator.o -ldora_operator_api_c -L../../target/debug/ -o ./build/liboperator_c_api.so

# 构建节点
CXX node-c-api/main.cc -lm -lrt -ldl -pthread -L../../target/debug -ldora_node_api_c -o ./build/node_c_api
#TBD#
#TBD#

Rust API

构建

alias CXX='clang++' # CXX='g++'
mkdir -p build

# 构建算子
cp ../../target/cxxbridge/dora-operator-api-cxx/src/lib.rs.h ./build/dora-operator-api.h
cp ../../target/cxxbridge/dora-operator-api-cxx/src/lib.rs.cc ./build/operator-bridge.cc
CXX -c ./operator-rust-api/operator.cc -std=c++17 -I./operator-rust-api -o operator-rust-api/operator.o -fPIC
CXX -c ./build/operator-bridge.cc -std=c++17 -I./operator-rust-api -o ./build/operator-bridge.o -fPIC
CXX -shared ./operator-rust-api/operator.o ./build/operator-bridge.o -ldora_operator_api_cxx -L../../target/debug/ -o ./build/liboperator_rust_api.so

# 构建节点
cp ../../target/cxxbridge/dora-node-api-cxx/src/lib.rs.h ./build/dora-node-api.h
cp ../../target/cxxbridge/dora-node-api-cxx/src/lib.rs.cc ./build/node-bridge.cc
CXX ./node-rust-api/main.cc ./build/node-bridge.cc -lm -lrt -ldl -pthread -L../../target/debug -ldora_node_api_cxx -o ./build/node_rust_api
#TBD#
#TBD#

运行

$ dora run dataflow.yaml

相关节点功能概览

  • node-c-api:使用C API对接收到的数据进行计数,并返回计数
  • node-rust-api: 使用Rust API对接收到的数据进行计数,并返回计数
  • operator-c-api:使用C API接受数据并除以2后发出
  • operator-rust-api:使用Rust API对接收到的所有消息进行计数,并将收到的消息发出

源码

完整源码请参考:dora-examples/c++-dataflow

数据流(Arrow Dataflow)

Apache Arrow 是通用的、列式格式的、快速数据交换和内存中分析工具。支持多种语言。

安装Arrow

更详细的安装说明与选项请参考Arrow官方安装文档

$ sudo apt update
$ sudo apt install -y -V ca-certificates lsb-release wget
$ wget https://packages.apache.org/artifactory/arrow/$(lsb_release --id --short | tr 'A-Z' 'a-z')/apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb
$ sudo apt install -y -V ./apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb
$ sudo apt update
$ sudo apt install -y -V libarrow-dev # For C++

构建

通过pkg-config --libs arrowpkg-config --cflags arrow获得系统安装的Arrow库相关的编译设置

$ mkdir build
$ cp ../../target/cxxbridge/dora-node-api-cxx/src/lib.rs.cc ./build/node-bridge.cc
$ cp ../../target/cxxbridge/dora-node-api-cxx/src/lib.rs.h ./build/dora-node-api.h
$ alias CXX=g++
$ CXX ./build/node-bridge.cc ./node-rust-api/main.cc -std=c++17 -lm -lrt -ldl -pthread -ldora_node_api_cxx -L../../target/debug/ $(pkg-config --libs arrow) $(pkg-config --cflags arrow) -o ./build/node_rust_api

运行

dora run dataflow.yml

源码

完整源码请参考:dora-examples/cxx-arrow-dataflow

C数据流

构建C API相关包

$ cargo build -p dora-node-api-c
$ cargo build -p dora-operator-api-c

Node

Source

$ alias C=gcc # 用clang亦可以
$ C node.c -lm -lrt -ldl -pthread -ldora_node_api_c -L../../target/debug/ -o ./build/c_node

Sink

$ C sink.c -lm -lrt -ldl -pthread -ldora_node_api_c -L../../target/debug/ -o ./build/c_sink

Operator

$ C -c operator.c -o build/operator.o -fPIC # 编译
$ C -shared build/operator.o -L../../target/debug/ -ldora_operator_api_c -o ./build/liboperator.so

源码

完整源码请参考:dora-examples/c-dataflow

CMake数据流

CMake是一个跨平台的构建系统,它允许开发者使用简单的脚本来描述项目的依赖关系和构建规则,从而实现跨平台的构建。C/C++ Dora项目也可以使用CMake来构建。

构建

$ cmake -DDORA_ROOT_DIR=../../ -B./build . # 通过DORA_ROOT_DIR变量指定Dora项目的根目录
$ cmake --build ./build
$ cmake --install ./build

运行

$ dora run dataflow.yml

源码

完整源码请参考:dora-examples/cmake-dataflow

ROS2数据流

确保ROS2环境已正确安装和配置

Dora通过ros2-client与ROS进行交互 C++ API为了与ROS通信,需要启用ROS2桥接功能。

准备相关依赖

由于例子与turtlesimAddTwoInts相关

$ sudo apt install ros-jazzy-turtlesim ros-jazzy-examples-rclcpp-minimal-service

生成带有ROS2 message 的 Dora API

$ source /opt/ros/jazzy/setup.bash
$ cargo build --package dora-node-api-cxx --features ros2-bridge

Note

  1. 当需要使用新的消息接口时,即包更新或AMENT_PREFIX_PATH更新时需要重新进行生成
  2. 在v0.3.13前,环境变量中残留的无消息ROS2 package会导致默认的--debug构建失败,请尝试在使用cargo生成API时添加--release参数

整理需要用到的头文件、C++源文件

$ mkdir build
$ cp ../../target/cxxbridge/dora-node-api-cxx/dora-node-api.cc ./build/dora-node-api.cc
$ cp ../../target/cxxbridge/dora-node-api-cxx/dora-node-api.h ./build/dora-node-api.h
$ cp ../../target/cxxbridge/dora-node-api-cxx/dora-ros2-bindings.cc ./build/dora-ros2-bindings.cc
$ cp ../../target/cxxbridge/dora-node-api-cxx/dora-ros2-bindings.h ./build/dora-ros2-bindings.h

Note

  1. 在v0.3.13版本前,所有的消息及与Dora相关的API生成在dora-node-api.hdora-ros2-bindings.h中,其对应的.cc需要与使用了该接口的C++源文件一起编译
  2. 在v0.3.13版本后,不同的ROS2消息生成在独立的文件中,具体可以查看生成API后查看target/cxxbridge/dora-node-api-cxx/install。请根据需要自行编译需要的C++源文件
  3. 截至v0.3.13版本(2025-11-24),Dora C++ API尚未支持ROS2中的Action通信机制

编译

$ alias CXX=g++ # clang++ 也可以
$ CXX ./node-rust-api/main.cc ./build/dora-ros2-bindings.cc ./build/dora-node-api.cc -std=c++17 -lm -lrt -ldl -lz -pthread -ldora_node_api_cxx -L ../../target/debug/ -o ./build/node_rust_api

Note

如果生成时使用了--release参数则需将链接目录target/debug/改为target/release

运行

打开另外两个终端

需要使用rmw_fastrtps_cppJazzy 中应该是默认的,如果在.bashrc等地方设置成了别的注意要设置回来。 更改设置后重启daemon,ros2 daemon stop, ros2 daemon start

启动turtlesim

$ source /opt/ros/jazzy/setup.bash
$ ros2 run turtlesim turtlesim_node

启动AddTwoInts服务

$ source /opt/ros/jazzy/setup.bash
$ ros2 run examples_rclcpp_minimal_service service_main

启动Dora节点

$ dora run dataflow.yml

源码

完整源码请参考:dora-examples/cxx-ros2-dataflow

CXX数据流

本示例展示如何使用C++创建dora算子(operator)和自定义节点(node)。

Dora目前尚未提供原生C++ API,但我们可以为C或Rust API创建适配器。operator-rust-apinode-rust-api文件夹实现了基于dora Rust API的示例算子和节点,使用cxx crate进行桥接。operator-c-apinode-c-api展示了如何基于dora的C API创建算子和节点。

项目结构

cxx-dataflow/
├── dataflow.yml          # 数据流定义文件
├── node-c-api/           # 基于C API的节点实现
├── node-rust-api/        # 基于Rust API的节点实现
├── operator-c-api/       # 基于C API的算子实现
└── operator-rust-api/    # 基于Rust API的算子实现

数据流配置

nodes:
  - id: cxx-node-rust-api
    path: build/node_rust_api
    inputs:
      tick: dora/timer/millis/300
    outputs:
      - counter

  - id: cxx-node-c-api
    path: build/node_c_api
    inputs:
      tick: cxx-node-rust-api/counter
    outputs:
      - counter

编译和运行

快速运行

使用run.rs二进制文件可以自动执行所有构建步骤并启动数据流:

cargo run --example cxx-dataflow

预期输出

运行成功后,你将看到类似以下的输出:

2026-01-02T00:55:11.194863Z  INFO dora_daemon::log:    Received input tick (counter: 1) build_id=None dataflow_id=Some("019b7c33-867d-7a38-ae09-3d76187688f0") node_id=Some("cxx-node-rust-api")
2026-01-02T00:55:11.195698Z  INFO dora_daemon::log:    Received input  (counter: 1) data: [1, ] build_id=None dataflow_id=Some("019b7c33-867d-7a38-ae09-3d76187688f0") node_id=Some("cxx-node-c-api")
2026-01-02T00:55:11.494528Z  INFO dora_daemon::log:    Received input tick (counter: 2) build_id=None dataflow_id=Some("019b7c33-867d-7a38-ae09-3d76187688f0") node_id=Some("cxx-node-rust-api")
2026-01-02T00:55:11.495464Z  INFO dora_daemon::log:    Received input  (counter: 2) data: [2, ] build_id=None dataflow_id=Some("019b7c33-867d-7a38-ae09-3d76187688f0") node_id=Some("cxx-node-c-api")
2026-01-02T00:55:11.794526Z  INFO dora_daemon::log:    Received input tick (counter: 3) build_id=None dataflow_id=Some("019b7c33-867d-7a38-ae09-3d76187688f0") node_id=Some("cxx-node-rust-api")
2026-01-02T00:55:11.795299Z  INFO dora_daemon::log:    Received input  (counter: 3) data: [3, ] build_id=None dataflow_id=Some("019b7c33-867d-7a38-ae09-3d76187688f0") node_id=Some("cxx-node-c-api")
2026-01-02T00:55:12.094486Z  INFO dora_daemon::log:    Received input tick (counter: 4) build_id=None dataflow_id=Some("019b7c33-867d-7a38-ae09-3d76187688f0") node_id=Some("cxx-node-rust-api")
2026-01-02T00:55:12.095222Z  INFO dora_daemon::log:    Received input  (counter: 4) data: [4, ] build_id=None dataflow_id=Some("019b7c33-867d-7a38-ae09-3d76187688f0") node_id=Some("cxx-node-c-api")
2026-01-02T00:55:12.394238Z  INFO dora_daemon::log:    Received input tick (counter: 5) build_id=None dataflow_id=Some("019b7c33-867d-7a38-ae09-3d76187688f0") node_id=Some("cxx-node-rust-api")
2026-01-02T00:55:12.395092Z  INFO dora_daemon::log:    Received input  (counter: 5) data: [5, ] build_id=None dataflow_id=Some("019b7c33-867d-7a38-ae09-3d76187688f0") node_id=Some("cxx-node-c-api")
2026-01-02T00:55:12.694241Z  INFO dora_daemon::log:    Received input tick (counter: 6) build_id=None dataflow_id=Some("019b7c33-867d-7a38-ae09-3d76187688f0") node_id=Some("cxx-node-rust-api")

日志显示了两个节点之间的数据流:cxx-node-rust-api接收定时器tick,然后将计数器值发送给cxx-node-c-api

手动构建

如果需要手动构建,请按以下步骤操作:

  1. 创建build文件夹
  2. 使用cargo build构建Rust API crates
  3. 编译C节点和算子库
  4. 构建dora coordinator和runtime
  5. 使用dora-daemon运行数据流

源码

完整源码请参考:dora-examples/cxx-dataflow

Python

为了更方便的管理Python包,Dora推荐使用uv进行管理

安装UV

$ sudo apt install curl # 安装curl,如果未安装
$ curl -LsSf https://astral.sh/uv/install.sh | sh

Python 样例

数据流

官方的Node Hub文件夹中提供了许多现成的节点 本例中用到的有

  • opencv-video-capture用于读取摄像头
  • dora-yolo用于进行目标检测
  • dora-rerun用于进行可视化

dataflow.yml除了用于描述输入输出外,还可以通过build字段进行简单的构建或安装

准备Python环境

$ uv venv -p 3.10 --seed

安装对应的包

当在dora build时加上--uv标签,会自动在使用pip前添加uv以使用uv管理的Python版本

$ dora build dataflow.yml --uv

运行

$ dora run dataflow.yml --uv

默认的视图中可能只包含照片项,在弹出的rerun窗口中右键时间轴上的/项,点击添加到新的视图中

运行效果

动态节点

$ dora build dataflow_dynamic.yml --uv # 安装所需要的节点
$ dora up # 启动本地的 daemon 和 coordinator
$ dora start dataflow_dynamic.yml --uv

在另外一个中端窗口运行

$ uv run opencv-plot --name plot

源码

完整源码请参考:dora-examples/python-dataflow

算子(Operator)

Operator提供了更加轻量化的方案,并且有更多Dora的高级功能,拥有更快的通信速度。

安装依赖

$ uv venv -p 3.11 --seed # 创建环境
$ uv pip install -e ../../apis/python/node # 安装Dora Python API
$ source .venv/bin/activate
$ pip install -r requirements.txt # 安装依赖,如果要体验dataflow_llm,则使用requirements_llm.txt

由于Operator暂未适配--uv标签作为启动参数,为了使用uv管理的Python,所以要在终端中source .venv/bin/activate

$ dora run dataflow.yml

运行效果

源码

完整源码请参考:dora-examples/python-dataflow

异步

$ uv venv -p 3.11 --seed # 创建环境
$ uv pip install -e ../../apis/python/node # 安装Dora Python API
$ dora build dataflow.yml --uv # 安装依赖

运行

$ dora run dataflow.yml --uv

本例较为简单展示了使用Python通过异步方式进行消息IO。

  • receive_data.py 异步接收数据
  • send_data.py 发送数据

源码

完整源码请参考:dora-examples/python-async

多Python环境共存

uv通过VIRTUAL_ENV环境变量可以切换不同的Python的环境,则只需要在dataflow.yml中配置即可

构建环境

$ uv venv -p 3.11 -n env_1
$ uv venv -p 3.11 -n env_2
$ dora build dataflow.yml --uv

运行

$ dora run dataflow.yml --uv

运行效果应与python-dataflow一致。

源码

完整源码请参考:dora-examples/python-multi-env

ROS2数据流

准备相关依赖

由于例子与turtlesimAddTwoInts相关

$ sudo apt install ros-jazzy-turtlesim ros-jazzy-examples-rclcpp-minimal-service

准备Python环境

$ uv venv -p 3.10 --seed
$ uv pip install -e ../../apis/node

启动

启动turtlesim

$ source /opt/ros/jazzy/setup.bash
$ ros2 run turtlesim turtlesim_node

启动AddTwoInts服务

$ source /opt/ros/jazzy/setup.bash
$ ros2 run examples_rclcpp_minimal_service service_main
$ source /opt/ros/jazzy/setup.bash
$ dora run dataflow.yml --uv

源码

完整源码请参考:dora-examples/python-ros2-dataflow

Python Dora-Zenoh集成示例

本示例展示如何使用Python将Dora与Zenoh连接进行双向通信。

概述

两个组件相互通信:

  1. Dora节点(Python):向Zenoh主题发布和订阅消息
  2. Zenoh应用(Python):通过Zenoh与Dora节点交换消息

结构

  • dataflow.yml:Dora数据流配置
  • dora_node.py:集成Zenoh的Dora节点实现
  • zenoh_app.py:独立的Zenoh应用程序
  • requirements.txt:Python依赖

前置条件

  • Python 3.8+
  • Dora已安装并在PATH中可用,或通过DORA环境变量设置
  • Python包:dora-rseclipse-zenoh

安装

安装所需的Python包:

pip install -r requirements.txt

工作原理

  • Dora节点

    • 每500ms向dora/data发布“Hello“消息
    • 订阅zenoh/data上的消息
    • 持续运行直到按Ctrl+C
  • Zenoh应用

    • 订阅dora/data
    • 接收5条消息后,开始向zenoh/data发布
    • 继续双向收发直到按Ctrl+C

运行示例

方式1:手动运行(推荐用于测试)

终端1 - 启动Dora数据流:

dora up
dora start dataflow.yml

终端2 - 运行Zenoh应用:

python3 zenoh_app.py

停止:

  • 在终端2按Ctrl+C停止Zenoh应用
  • 在终端1按Ctrl+C停止Dora节点,或运行:
dora destroy dataflow.yml

方式2:使用Dora Daemon

dora daemon --run-dataflow dataflow.yml

然后在另一个终端:

python3 zenoh_app.py

预期输出

来自dora_node.py:

Initializing Zenoh session...
Declaring Zenoh publisher for 'dora/data'...
Declaring Zenoh subscriber for 'zenoh/data'...
Dora node with Zenoh integration started!
Press Ctrl+C to stop...
Publishing message: Hello from Dora node! Message #1
Publishing message: Hello from Dora node! Message #2
Publishing message: Hello from Dora node! Message #3
...
>> [Subscriber] Received PUT ('zenoh/data': 'Hello from Zenoh app, payload counter: 0')
>> [Subscriber] Received PUT ('zenoh/data': 'Hello from Zenoh app, payload counter: 1')
...
(持续运行直到按Ctrl+C)

来自zenoh_app.py:

Opening Zenoh session...
Subscribing to dora/data...
Waiting for 5 messages from Dora node before publishing...
>> [Subscriber] Received PUT ('dora/data': 'Hello from Dora node! Message #1')
>> [Subscriber] Received PUT ('dora/data': 'Hello from Dora node! Message #2')
...
>> [Subscriber] Received PUT ('dora/data': 'Hello from Dora node! Message #5')

Received 5 messages! Creating publisher for 'zenoh/data'...
Publishing to Dora node (Press Ctrl+C to stop)...

<< [Publisher] Sent payload(counter = 0)
>> [Subscriber] Received PUT ('dora/data': 'Hello from Dora node! Message #6')
<< [Publisher] Sent payload(counter = 1)
>> [Subscriber] Received PUT ('dora/data': 'Hello from Dora node! Message #7')
...
(持续双向通信直到按Ctrl+C)

故障排除

  • 确保Zenoh可以通信(检查防火墙设置)
  • 确保已安装dora-rseclipse-zenoh
  • 检查是否使用Python 3.8+

源码

完整源码请参考:dora-examples/python-zenoh-dataflow

Rust

Rust 样例

Rust数据流

源码

完整源码请参考:dora-examples/rust-dataflow

Rust网址数据流

源码

完整源码请参考:dora-examples/rust-dataflow-url

通过git获取节点

源码

完整源码请参考:dora-examples/rust-dataflow-git

Rust ROS2数据流

源码

完整源码请参考:dora-examples/rust-ros2-dataflow

Dora-Zenoh集成示例

本示例展示如何将Dora与Zenoh连接进行双向通信。

概述

两个组件相互通信:

  1. Dora节点:向Zenoh主题发布和订阅消息
  2. Zenoh应用:通过Zenoh与Dora节点交换消息

结构

  • dataflow.yml:Dora数据流配置
  • dora-node/:集成Zenoh的Dora节点实现
  • zenoh-app/:订阅数据的独立Zenoh应用程序
  • main.rs:Dora数据流运行器

前置条件

  • Rust和Cargo
  • Dora已安装并在PATH中可用,或通过DORA环境变量设置
  • Zenoh依赖已安装

确保DORA环境变量设置正确:

export DORA=/Users/demo/dora

工作原理

nodes:
    - id: dora-zenoh-publisher
      build: bash -c "cd dora-node && cargo build --release"
      path: ./dora-node/target/aarch64-apple-darwin/release/dora-node
      inputs:
          tick: dora/timer/millis/500
  • id:节点标识符
  • build:编译节点的命令
  • path:编译后二进制文件的位置
  • inputs:Dora提供一个每500ms发送tick的定时器给此节点

Dora节点

  • dora/data发布“Hello“消息
  • 订阅zenoh/data上的消息

Zenoh应用

  • 订阅zenoh/data
  • dora/data发布消息

运行示例

cargo run --release --example zenoh-dataflow

预期输出

2025-11-02T18:10:49.943542Z  INFO dora_daemon::log:    Initializing Zenoh session... build_id=None dataflow_id=Some("019a45c3-c5d2-7725-85d1-e741573b765e") node_id=Some("dora-zenoh-publisher")
2025-11-02T18:10:49.951918Z  INFO dora_daemon::log:    Declaring Zenoh publisher for 'dora/data'... build_id=None dataflow_id=Some("019a45c3-c5d2-7725-85d1-e741573b765e") node_id=Some("dora-zenoh-publisher")
>> [Subscriber] Received PUT ('dora/data': 'Hello from Dora node! Message #1')
2025-11-02T18:10:49.962553Z  INFO dora_daemon::log:    Declaring Zenoh subscriber for 'zenoh/data'... build_id=None dataflow_id=Some("019a45c3-c5d2-7725-85d1-e741573b765e") node_id=Some("dora-zenoh-publisher")
2025-11-02T18:10:49.972699Z  INFO dora_daemon::log:    Dora node with Zenoh integration started! build_id=None dataflow_id=Some("019a45c3-c5d2-7725-85d1-e741573b765e") node_id=Some("dora-zenoh-publisher")
2025-11-02T18:10:49.977408Z  INFO dora_daemon::log:    Publishing message: Hello from Dora node! Message #1 build_id=None dataflow_id=Some("019a45c3-c5d2-7725-85d1-e741573b765e") node_id=Some("dora-zenoh-publisher")
2025-11-02T18:10:50.444696Z  INFO dora_daemon::log:    Publishing message: Hello from Dora node! Message #2 build_id=None dataflow_id=Some("019a45c3-c5d2-7725-85d1-e741573b765e") node_id=Some("dora-zenoh-publisher")
>> [Subscriber] Received PUT ('dora/data': 'Hello from Dora node! Message #2')
2025-11-02T18:10:50.944559Z  INFO dora_daemon::log:    Publishing message: Hello from Dora node! Message #3 build_id=None dataflow_id=Some("019a45c3-c5d2-7725-85d1-e741573b765e") node_id=Some("dora-zenoh-publisher")
>> [Subscriber] Received PUT ('dora/data': 'Hello from Dora node! Message #3')
2025-11-02T18:10:51.445510Z  INFO dora_daemon::log:    Publishing message: Hello from Dora node! Message #4 build_id=None dataflow_id=Some("019a45c3-c5d2-7725-85d1-e741573b765e") node_id=Some("dora-zenoh-publisher")

源码

完整源码请参考:dora-examples/rust-zenoh-dataflow

进阶

Dora 官方提供了很多开箱即用的Node-hub, 其中包括但不限于:

可视化

Rerun为多种物理AI数据提供了非常优秀的可视化方案, 本例中用dora-rerun节点可视化opencv-video-capture节点采集到的图像。

概述

dataflow.yml 定义了一个简单的数据流图,包含两个节点:

  • camera: 使用 opencv-video-capture 从摄像头捕获视频帧
  • rerun: 使用 dora-rerun 在 Rerun 可视化工具中显示捕获的帧

开始使用

确保已安装 dora

pip install dora-rs

构建和运行

cd examples/rerun-viewer
dora build dataflow.yml
dora up
dora start dataflow.yml

配置

可以通过 dataflow.yml 中的环境变量配置 camera 节点:

  • CAPTURE_PATH: 相机设备索引(默认:0
  • IMAGE_WIDTH: 输出图像宽度(默认:640
  • IMAGE_HEIGHT: 输出图像高度(默认:480
  • ENCODING: 图像编码格式(默认:rgb8

源码

完整源码请参考:dora-examples/rerun-viewer

相机示例

本示例展示如何使用 dora-rs 捕获摄像头画面并显示。

概述

数据流定义了一个简单的图,包含两个节点:

  • camera: 使用 opencv-video-capture 从摄像头捕获画面
  • plot: 使用 opencv-plot 在窗口中显示捕获的画面

开始使用

确保已安装 dora

pip install dora-rs

构建和运行

cd examples/camera
dora build dataflow.yml
dora up
dora start dataflow.yml

数据流配置

nodes:
  - id: camera
    build: pip install opencv-video-capture
    path: opencv-video-capture
    inputs:
      tick: dora/timer/millis/20
    outputs:
      - image
    env:
      CAPTURE_PATH: 0
      IMAGE_WIDTH: 640
      IMAGE_HEIGHT: 480

  - id: plot
    build: pip install opencv-plot
    path: opencv-plot
    inputs:
      image:
        source: camera/image
        queue_size: 1

配置选项

可以通过环境变量配置相机节点:

  • CAPTURE_PATH: 相机设备索引(默认: 0
  • IMAGE_WIDTH: 输出图像宽度(默认: 640
  • IMAGE_HEIGHT: 输出图像高度(默认: 480

Jupyter Notebook 变体

提供了 Jupyter notebook 变体,包含 dataflow_jupyter.ymlnotebook.ipynb

dora build dataflow_jupyter.yml
dora up
dora start dataflow_jupyter.yml
# 然后在 Jupyter 中打开 notebook.ipynb

源码

完整源码请参考:dora-examples/camera

AV1 编码示例

本示例演示使用 rav1e(编码器)和 dav1d(解码器)进行实时 AV1 视频编码和解码,并通过 Rerun 进行可视化。

源代码:av1-encoding

概述

该数据流捕获摄像头画面,使用 AV1 编码,解码后再次编码,再解码,最后显示结果。这模拟了一个往返编码管道,用于测试视频压缩质量。

camera -> rav1e (编码) -> dav1d (解码) -> rav1e (编码) -> dav1d (解码) -> rerun (显示)

节点

  • camera:使用 opencv-video-capture 从摄像头捕获画面
  • rav1e-local:使用 dora-rav1e 将画面编码为 AV1 格式
  • dav1d-remote:使用 dora-dav1d 解码 AV1 画面
  • rav1e-remote:对解码后的画面重新编码为 AV1
  • dav1d-local:最终解码 AV1 画面
  • plot:使用 dora-rerun 在 Rerun 查看器中可视化解码后的画面

前置条件

  • Rust 工具链(用于构建 rav1e/dav1d 节点)
  • Python 3.8+
  • 摄像头

快速开始

1. 安装 dora

# 安装 dora CLI
cargo install dora-cli

# 安装 Python 包(版本必须与 CLI 匹配)
pip install dora-rs

重要:确保 dora CLI 版本与 dora-rs Python 包版本匹配:

dora --version      # 检查 CLI 版本
pip show dora-rs    # 检查 Python 包版本

2. 克隆 dora-hub(获取节点源码)

git clone https://github.com/dora-rs/dora-hub.git
cd dora-hub

3. 构建节点

# 构建 AV1 编码器/解码器节点
cargo build -p dora-rav1e --release
cargo build -p dora-dav1d --release

# 安装 Python 节点
pip install -e node-hub/opencv-video-capture
pip install -e node-hub/dora-rerun

4. 运行数据流

cd examples/av1-encoding

# 启动 dora 守护进程
dora up

# 构建并启动数据流
dora build dataflow.yml
dora start dataflow.yml

5. 查看输出

连接 Rerun 查看器以查看视频流:

rerun --connect rerun+http://127.0.0.1:9876/proxy

6. 停止数据流

dora stop

配置

相机节点

通过 dataflow.yml 中的环境变量进行配置:

变量描述默认值
CAPTURE_PATH相机设备索引0
IMAGE_WIDTH输出图像宽度1280
IMAGE_HEIGHT输出图像高度720

AV1 编码器 (rav1e)

变量描述默认值
RAV1E_SPEED编码速度预设(0-10,越高越快)10

数据流变体

本示例包含多种数据流配置:

  • dataflow.yml:本地机器版本(单机,推荐)
  • dataflow_distributed.yml:分布式部署版本(需要在 encoderdecoder 机器上运行 dora 守护进程)
  • dataflow_reachy.yml:Reachy 机器人深度相机配置

故障排除

版本不匹配错误

如果出现类似 invalid type: map, expected a YAML tag starting with '!' 的错误:

# 检查版本是否匹配
dora --version
pip show dora-rs

# 如需升级
cargo install dora-cli --version X.Y.Z
pip install dora-rs==X.Y.Z

节点未找到错误

如果节点启动失败并显示 “No such file or directory”:

  1. 确保已构建 Rust 节点:cargo build -p dora-rav1e -p dora-dav1d --release
  2. 检查 dataflow.yml 中的 path 是否指向正确的二进制文件位置

相机无法工作

  • 在 macOS 上检查相机权限:系统偏好设置 > 隐私与安全性 > 相机
  • 尝试不同的 CAPTURE_PATH 值(0、1、2…)

架构

+--------+     +-------------+     +-------------+
| camera | --> | rav1e-local | --> | dav1d-remote|
+--------+     +-------------+     +-------------+
                                          |
                                          v
+------+     +------------+     +--------------+
| plot | <-- | dav1d-local| <-- | rav1e-remote |
+------+     +------------+     +--------------+

源代码

深度相机

本示例演示如何从深度相机捕获RGB图像和深度数据,并在Rerun中进行可视化。

概述

数据流从深度相机(Intel RealSense或iOS LiDAR)捕获帧,输出RGB图像和深度数据,并在Rerun查看器中显示。

depth_camera -> rerun (显示 RGB + 深度)

支持的设备

  • Intel RealSense:D400系列深度相机(D415、D435、D455等)
  • iOS LiDAR:带有LiDAR扫描仪的iPhone Pro / iPad Pro

节点

  • camera:从深度相机捕获RGB图像和深度数据
    • Intel RealSense使用dora-pyrealsense
    • iOS设备使用dora-ios-lidar
  • plot:使用dora-rerun在Rerun查看器中可视化RGB图像和深度数据

前置条件

  • Python 3.8+
  • 以下深度相机之一:
    • Intel RealSense D400系列相机
    • 带有LiDAR的iPhone Pro / iPad Pro

Intel RealSense

iOS LiDAR

  • 带有LiDAR的iOS设备(iPhone 12 Pro或更新版本,iPad Pro 2020或更新版本)
  • 在iOS设备上安装Record3D应用

开始使用

1. 安装dora

# 安装dora CLI
cargo install dora-cli

# 安装Python包(必须与CLI版本匹配)
pip install dora-rs

重要:确保dora CLI版本与dora-rs Python包版本匹配:

dora --version      # 检查CLI版本
pip show dora-rs    # 检查Python包版本

2. 运行数据流

Intel RealSense

cd examples/depth_camera

# 启动dora守护进程
dora up

# 构建并启动数据流
dora build realsense.yaml
dora start realsense.yaml

iOS LiDAR

  1. 在iOS设备上打开Record3D应用
  2. 在Record3D设置中启用USB流模式
  3. 通过USB连接iOS设备
cd examples/depth_camera

# 启动dora守护进程
dora up

# 构建并启动数据流
dora build ios.yaml
dora start ios.yaml

3. 查看输出

连接Rerun查看器以查看RGB和深度流:

rerun --connect rerun+http://127.0.0.1:9876/proxy

4. 停止数据流

dora stop

配置

iOS LiDAR节点

通过ios.yamlios-dev.yaml中的环境变量进行配置:

变量描述默认值
IMAGE_WIDTH输出图像宽度640
IMAGE_HEIGHT输出图像高度480

数据流变体

本示例包含多个数据流配置:

  • realsense.yaml:Intel RealSense相机(生产环境)
  • realsense-dev.yaml:Intel RealSense相机(开发环境,可编辑安装)
  • ios.yaml:iOS LiDAR相机(生产环境)
  • ios-dev.yaml:iOS LiDAR相机(开发环境,可编辑安装)

故障排除

Intel RealSense未检测到

  • 确保已安装librealsense2 SDK
  • 检查USB连接(使用USB 3.0端口以获得最佳性能)
  • 如果权限被拒绝,尝试使用sudo运行:使用包含sudo的realsense-dev.yaml

iOS设备未检测到

  • 确保Record3D应用正在运行且USB流已启用
  • 检查iOS设备与计算机之间的USB连接
  • 在出现提示时信任计算机

版本不匹配错误

如果看到类似invalid type: map, expected a YAML tag starting with '!'的错误:

# 检查版本是否匹配
dora --version
pip show dora-rs

# 如需升级
cargo install dora-cli --version X.Y.Z
pip install dora-rs==X.Y.Z

架构

+---------------+     +------+
| depth_camera  | --> | plot |
| (image+depth) |     +------+
+---------------+

源码

完整源码请参考:dora-examples/depth_camera

MediaPipe 姿态识别

本示例演示使用 MediaPipe 和 dora-rs 进行人体姿态检测,并通过 Rerun 进行可视化。

源代码:mediapipe

概述

该数据流从摄像头捕获画面,使用 MediaPipe 检测人体姿态关键点,并在 Rerun 中可视化结果。

camera -> dora-mediapipe (姿态检测) -> rerun (显示)

节点

  • camera:使用 opencv-video-capture 从摄像头捕获画面
  • dora-mediapipe:处理画面以检测人体姿态关键点
  • plot:使用 dora-rerun 可视化摄像头画面和检测到的姿态点

前置条件

  • 连接到电脑的摄像头
  • Python 3.8+
  • dora-rs

快速开始

1. 安装 dora

# 安装 dora CLI
cargo install dora-cli

# 安装 Python 包(版本必须与 CLI 匹配)
pip install dora-rs

重要:确保 dora CLI 版本与 dora-rs Python 包版本匹配:

dora --version      # 检查 CLI 版本
pip show dora-rs    # 检查 Python 包版本

2. 构建并运行

cd examples/mediapipe

# 构建数据流
dora build dataflow.yml

# 启动 dora 守护进程
dora up

# 启动数据流
dora start dataflow.yml

3. 查看输出

连接 Rerun 查看器以查看带有姿态关键点的视频流:

rerun --connect rerun+http://127.0.0.1:9876/proxy

如果默认未显示姿态点,请尝试在 Rerun 界面中添加 2D 查看器。

4. 停止数据流

dora stop

演示

演示视频

配置

相机节点

通过 dataflow.yml 中的环境变量进行配置:

变量描述默认值
CAPTURE_PATH相机设备索引0
IMAGE_WIDTH输出图像宽度640
IMAGE_HEIGHT输出图像高度480
ENCODING图像编码格式rgb8

输出

dora-mediapipe 节点输出:

  • points2d:每帧检测到的 2D 姿态关键点坐标

RealSense 变体

提供 RealSense 深度相机变体用于 3D 姿态估计。详情请参阅 dora-hub 中的原始示例。

架构

+--------+     +----------------+     +------+
| camera | --> | dora-mediapipe | --> | plot |
+--------+     +----------------+     +------+

源代码

物体识别示例

本示例演示使用 YOLO(You Only Look Once)和 dora-rs 进行实时物体检测,并通过 Rerun 进行可视化。

源代码:object-detection

概述

该数据流从摄像头捕获画面,通过 YOLO 进行物体检测,并在 Rerun 中显示带有边界框的结果。

camera -> dora-yolo (物体检测) -> rerun (显示带边界框)

节点

  • camera:使用 opencv-video-capture 从摄像头捕获画面
  • object-detection:使用 dora-yolo (YOLOv8) 检测画面中的物体
  • plot:使用 dora-rerun 可视化摄像头画面和边界框

前置条件

  • 连接到电脑的摄像头
  • Python 3.8+
  • dora-rs

快速开始

1. 安装 dora

# 安装 dora CLI
cargo install dora-cli

# 安装 Python 包(版本必须与 CLI 匹配)
pip install dora-rs

重要:确保 dora CLI 版本与 dora-rs Python 包版本匹配:

dora --version      # 检查 CLI 版本
pip show dora-rs    # 检查 Python 包版本

2. 构建并运行

cd examples/object-detection

# 构建数据流
dora build yolo.yml

# 启动 dora 守护进程
dora up

# 启动数据流
dora start yolo.yml

使用 UV(推荐)

uv venv --seed -p 3.11
dora build yolo.yml --uv
dora run yolo.yml --uv

3. 查看输出

连接 Rerun 查看器以查看带有检测物体的视频流:

rerun --connect rerun+http://127.0.0.1:9876/proxy

4. 停止数据流

dora stop

配置

相机节点

通过 yolo.yml 中的环境变量进行配置:

变量描述默认值
CAPTURE_PATH相机设备索引0
IMAGE_WIDTH输出图像宽度640
IMAGE_HEIGHT输出图像高度480

YOLO 节点

dora-yolo 节点默认使用 YOLOv8。它可以检测 COCO 数据集中的 80 种常见物体类别,包括:

  • 人、车辆(汽车、公交车、卡车、自行车、摩托车)
  • 动物(狗、猫、鸟、马等)
  • 常见物品(椅子、桌子、笔记本电脑、手机等)

输出

dora-yolo 节点输出:

  • bbox:每帧检测到的物体的边界框坐标和类别标签

架构

+--------+     +------------------+     +------+
| camera | --> | object-detection | --> | plot |
+--------+     | (dora-yolo)      |     +------+
    |          +------------------+         ^
    |                                       |
    +---------------------------------------+
                  (image)

故障排除

模型下载

首次运行时,YOLO 会自动下载模型权重。根据网络连接情况,这可能需要一些时间。

相机无法工作

  • 在 macOS 上检查相机权限:系统偏好设置 > 隐私与安全性 > 相机
  • 尝试不同的 CAPTURE_PATH 值(0、1、2…)

版本不匹配错误

如果出现类似 invalid type: map, expected a YAML tag starting with '!' 的错误:

# 检查版本是否匹配
dora --version
pip show dora-rs

# 如需升级
cargo install dora-cli --version X.Y.Z
pip install dora-rs==X.Y.Z

源代码

LLM 语音助手示例

本示例演示使用 Qwen 大语言模型和 dora-rs 构建语音交互 AI 助手。它可以捕获语音、转录文字、使用 Qwen 生成回复,并将回复朗读出来。

源代码:llm

概述

该数据流创建了一个完整的语音助手管道:

麦克风 -> VAD -> Whisper (语音转文字) -> Qwen (LLM) -> Kokoro (文字转语音) -> 扬声器
                                             |
                                             v
                                          rerun (显示)

节点

  • dora-microphone:从麦克风捕获音频
  • dora-vad:语音活动检测 - 检测你何时在说话
  • dora-distil-whisper:使用 Distil-Whisper 模型进行语音转文字
  • dora-qwen:大语言模型 (Qwen) 用于生成回复
  • dora-kokoro-tts:使用 Kokoro 进行文字转语音
  • dora-pyaudio:通过扬声器播放音频
  • plot:使用 dora-rerun 在 Rerun 查看器中可视化对话

前置条件

  • Python 3.11+
  • dora-rs
  • 麦克风和扬声器
  • 足够的 GPU/RAM 用于本地运行 LLM(或 API 访问)

系统依赖

macOS

brew install portaudio
brew install espeak-ng

Linux

sudo apt-get install portaudio19-dev
sudo apt-get install espeak

快速开始

1. 安装 dora

# 安装 dora CLI
cargo install dora-cli

# 安装 Python 包(版本必须与 CLI 匹配)
pip install dora-rs

重要:确保 dora CLI 版本与 dora-rs Python 包版本匹配:

dora --version      # 检查 CLI 版本
pip show dora-rs    # 检查 Python 包版本

2. 构建并运行

cd examples/llm

# 创建虚拟环境
uv venv --seed -p 3.11

# 构建数据流
dora build qwen-dev.yml --uv

# 运行数据流
dora run qwen-dev.yml --uv

3. 查看输出

连接 Rerun 查看器以查看对话:

rerun --connect rerun+http://127.0.0.1:9876/proxy

4. 交互

直接对着麦克风说话。助手会:

  1. 检测你何时开始/停止说话 (VAD)
  2. 将你的语音转录为文字 (Whisper)
  3. 使用 Qwen LLM 生成回复
  4. 将回复朗读给你 (Kokoro TTS)

5. 停止数据流

dora stop

配置

Whisper 节点

变量描述默认值
TARGET_LANGUAGE转录目标语言english

TTS 节点

变量描述默认值
ACTIVATION_WORDS触发 TTS 回复的关键词you

数据流变体

  • qwen-dev.yml:标准语音助手
  • qwen-dev-interruption.yml:支持打断的语音助手(当你开始说话时会停止朗读)

架构

+------------+     +---------+     +------------------+
|   麦克风   | --> |   VAD   | --> | distil-whisper   |
+------------+     +---------+     | (语音转文字)     |
                                   +------------------+
                                            |
                                            v
+------------+     +-------------+     +---------+
|  pyaudio   | <-- | kokoro-tts  | <-- |  qwen   |
| (扬声器)   |     | (文字转     |     |  (LLM)  |
+------------+     |   语音)     |     +---------+
                   +-------------+          |
                                            v
                                       +--------+
                                       |  plot  |
                                       | (rerun)|
                                       +--------+

故障排除

麦克风无法工作

  • 在系统设置中检查麦克风权限
  • 确保选择了正确的音频输入设备
  • 先用其他应用测试麦克风

没有音频输出

  • 检查扬声器/耳机连接
  • 验证音频输出设备设置
  • 确保 portaudio 安装正确

模型下载

首次运行时,模型(Whisper、Qwen、Kokoro)会自动下载。根据网络连接和模型大小,这可能需要一些时间。

版本不匹配错误

如果出现类似 invalid type: map, expected a YAML tag starting with '!' 的错误:

# 检查版本是否匹配
dora --version
pip show dora-rs

# 如需升级
cargo install dora-cli --version X.Y.Z
pip install dora-rs==X.Y.Z

源代码

OpenAI服务器示例

本示例演示如何使用dora-openai-server在Dora数据流中创建一个OpenAI兼容的API服务器。

概述

dora-openai-server节点暴露一个OpenAI兼容的HTTP API,可以接收来自标准OpenAI客户端的请求,并通过Dora数据流进行路由。这使得LLM功能可以与其他Dora节点无缝集成。

注意:Dora OpenAI Server仍处于实验阶段,未来可能会有变化。

OpenAI客户端 -> dora-openai-server -> dora-echo -> 响应

节点

  • dora-openai-server:在http://localhost:8000暴露OpenAI兼容的API
    • 处理/v1/chat/completions端点
    • 支持文本和图像输入(URL和base64)
  • dora-echo:简单的回显节点,将接收到的输入作为响应返回

前置条件

  • Python 3.11+
  • uv包管理器
  • 已安装dora-cli
  • Cargo(用于构建Rust组件)

开始使用

1. 设置环境

cd examples/openai-server

# 创建虚拟环境
uv venv -p 3.11 --seed

# 安装dora Python API(本地开发时)
uv pip install -e ../../apis/python/node --reinstall

2. 构建并运行数据流

# 构建数据流
dora build dataflow.yml --uv

# 启动dora守护进程
dora up

# 运行数据流
dora run dataflow.yml --uv

3. 使用OpenAI客户端测试

在另一个终端中:

python openai_api_client.py

4. 停止数据流

dora stop

API功能

OpenAI服务器支持:

聊天补全

标准聊天补全请求:

from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="dummy_api_key")

response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Hello!"},
    ],
)

图像输入(URL)

response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "What is in this image?"},
                {
                    "type": "image_url",
                    "image_url": {"url": "https://example.com/image.jpg"},
                },
            ],
        }
    ],
)

图像输入(Base64)

response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "What is in this image?"},
                {
                    "type": "image_url",
                    "image_url": {"url": "data:image/png;base64,iVBORw0KGgo..."},
                },
            ],
        }
    ],
)

数据流配置

默认的dataflow.yml

nodes:
  - id: dora-openai-server
    build: pip install dora-openai-server
    path: dora-openai-server
    outputs:
      - v1/chat/completions
    inputs:
      v1/chat/completions: dora-echo/echo

  - id: dora-echo
    build: pip install dora-echo
    path: dora-echo
    inputs:
      echo: dora-openai-server/v1/chat/completions
    outputs:
      - echo

数据流变体

  • dataflow.yml:基本回显示例(Python)
  • dataflow-rust.yml:Rust变体
  • qwenvl.yml:与Qwen VL模型集成

架构

+----------------+     +------------------+     +-----------+
| OpenAI客户端   | --> | dora-openai-     | --> | dora-echo |
| (HTTP请求)     |     | server           |     |           |
+----------------+     | (localhost:8000) |     +-----------+
                       +------------------+           |
                              ^                       |
                              +-----------------------+
                                   (响应)

源码

完整源码请参考:dora-examples/openai-server

语音到语音示例

本示例演示使用dora-rs构建的实时语音到语音管道。它捕获您的声音,使用Whisper进行转录,并使用Kokoro TTS将转录内容朗读出来。

概述

数据流创建了一个完整的语音回声管道:

麦克风 -> VAD -> Whisper (STT) -> Kokoro (TTS) -> 扬声器
                                       |
                                       v
                                   rerun (显示)

节点

  • dora-microphone:从麦克风捕获音频
  • dora-vad:语音活动检测 - 检测您何时在说话
  • dora-distil-whisper:使用Distil-Whisper模型进行语音转文字
  • dora-kokoro-tts:使用Kokoro进行文字转语音输出
  • dora-pyaudio:通过扬声器播放音频
  • dora-rerun:在Rerun查看器中可视化转录内容

前置条件

  • Python 3.11+
  • dora-rs
  • 麦克风和扬声器
  • 已安装portaudio和espeak-ng

系统依赖

macOS

brew install portaudio
brew install espeak-ng

Linux

sudo apt-get install portaudio19-dev
sudo apt-get install espeak

开始使用

1. 安装dora

# 安装dora CLI
cargo install dora-cli

# 安装Python包(必须与CLI版本匹配)
pip install dora-rs

重要:确保dora CLI版本与dora-rs Python包版本匹配:

dora --version      # 检查CLI版本
pip show dora-rs    # 检查Python包版本

2. 构建并运行

cd examples/speech-to-speech

# 创建虚拟环境
uv venv --seed -p 3.11

# 构建数据流
dora build kokoro-dev.yml --uv

# 运行数据流
dora run kokoro-dev.yml --uv

3. 查看输出

连接Rerun查看器以查看转录内容:

rerun --connect rerun+http://127.0.0.1:9876/proxy

4. 交互

只需对着麦克风说话。管道将:

  1. 检测您何时开始/停止说话(VAD)
  2. 将您的语音转录为文字(Whisper)
  3. 将转录内容朗读给您(Kokoro TTS)

5. 停止数据流

dora stop

配置

Whisper节点

变量描述默认值
TARGET_LANGUAGE转录的目标语言english

数据流变体

  • kokoro-dev.yml:使用Kokoro TTS进行语音合成
  • outtetts-dev.yml:使用OuteTTS进行语音合成
  • outtetts.yml:使用OuteTTS的生产版本

架构

+------------+     +---------+     +------------------+
|   麦克风   | --> |   VAD   | --> | distil-whisper   |
+------------+     +---------+     | (语音转文字)     |
                                   +------------------+
                                            |
                                            v
+------------+     +-------------+     +---------+
|  pyaudio   | <-- | kokoro-tts  | <-- | whisper |
| (扬声器)   |     | (文字转     |     |  (STT)  |
+------------+     |   语音)     |     +---------+
                   +-------------+          |
                                            v
                                       +--------+
                                       |  plot  |
                                       | (rerun)|
                                       +--------+

故障排除

麦克风无法工作

  • 在系统设置中检查麦克风权限
  • 确保选择了正确的音频输入设备
  • 先用其他应用程序测试麦克风

无音频输出

  • 检查扬声器/耳机连接
  • 验证音频输出设备设置
  • 确保portaudio已正确安装

PyAudio架构不匹配(macOS Apple Silicon)

如果看到类似incompatible architecture (have 'x86_64', need 'arm64')的错误:

# 删除旧的pyaudio并使用正确的架构重新安装
pip uninstall pyaudio
ARCHFLAGS="-arch arm64" pip install --no-cache-dir --no-binary :all: pyaudio

模型下载

首次运行时,模型(Whisper、Kokoro)将自动下载。这可能需要一些时间,取决于您的网络连接和模型大小。

版本不匹配错误

如果看到类似invalid type: map, expected a YAML tag starting with '!'的错误:

# 检查版本是否匹配
dora --version
pip show dora-rs

# 如需升级
cargo install dora-cli --version X.Y.Z
pip install dora-rs==X.Y.Z

源码

完整源码请参考:dora-examples/speech-to-speech

语音到文字

概述

此数据流创建一个完整的语音转文字流水线:

麦克风 -> VAD -> Whisper (STT) -> Rerun (显示)

流水线从麦克风捕获音频,检测您何时在说话,使用 Whisper 模型将语音转录为文字,并在 Rerun 查看器中显示结果。

节点

  • dora-microphone:从麦克风捕获音频
  • dora-vad:语音活动检测 - 检测您何时在说话
  • dora-distil-whisper:使用 Distil-Whisper 模型进行语音转文字
  • dora-rerun:在 Rerun 查看器中可视化转录结果

先决条件

  • Python 3.11+
  • dora-rs
  • 麦克风
  • uv(Python 包管理器)

快速开始

1. 安装 dora

# 安装 dora CLI
cargo install dora-cli

# 或安装 Python 包(必须与 CLI 版本匹配)
pip install dora-rs

2. 构建和运行

cd examples/speech-to-text

# 创建虚拟环境
uv venv --seed -p 3.11

# 构建数据流
dora build whisper.yml --uv

# 运行数据流
dora run whisper.yml --uv

3. 查看结果

# 连接到 Rerun 查看器
rerun --connect rerun+http://127.0.0.1:9876/proxy

配置

Whisper 节点配置

变量描述默认值
TARGET_LANGUAGE转录目标语言english

数据流变体

  • whisper.yml:使用预打包节点的生产版本
  • whisper-dev.yml:用于本地开发的开发版本

架构

+------------+     +---------+     +------------------+
|   麦克风   | --> |   VAD   | --> | distil-whisper   |
+------------+     +---------+     | (语音转文字)     |
                                   +------------------+
                                            |
                                            v
                                       +--------+
                                       | rerun  |
                                       | (显示) |
                                       +--------+

故障排除

麦克风问题

  • 检查系统麦克风权限
  • 验证是否选择了正确的音频输入设备
  • 首先在其他应用程序中测试麦克风

模型下载缓慢

  • 首次运行需要下载 Whisper 模型,可能需要一些时间
  • 确保网络连接稳定
  • 模型在首次下载后会被缓存

中国用户可以使用 hf-mirror 镜像加速模型下载:

HF_ENDPOINT=https://hf-mirror.com dora build whisper.yml --uv

Rerun 版本不匹配

  • 如果看到版本警告,请安装匹配的 Rerun SDK:
    pip install rerun-sdk==<version>
    

源码

完整源码请参考:dora-examples/speech-to-text

物体追踪

概述

此数据流使用 Facebook 的 CoTracker 创建实时物体追踪流水线:

相机 -> 物体检测 -> CoTracker -> Rerun (显示)

流水线从相机捕获视频,使用 YOLO 检测物体,使用 CoTracker 在帧之间追踪检测到的物体,并在 Rerun 查看器中显示结果。

节点

  • opencv-video-capture:从相机捕获视频
  • dora-yolo:使用 YOLOv8 进行物体检测
  • dora-cotracker:使用 Facebook CoTracker3 进行点追踪
  • dora-rerun:在 Rerun 查看器中可视化追踪结果

先决条件

  • Python 3.10+
  • dora-rs
  • 相机(摄像头)
  • 推荐 GPU(CUDA、MPS 或 CPU 回退)

快速开始

1. 安装 dora

# 安装 dora CLI
cargo install dora-cli

# 或安装 Python 包(必须与 CLI 版本匹配)
pip install dora-rs

2. 构建和运行

cd examples/tracker

# 构建数据流
dora build facebook_cotracker.yml

# 运行数据流
dora run facebook_cotracker.yml

3. 查看结果

# 连接到 Rerun 查看器
rerun --connect rerun+http://127.0.0.1:9876/proxy

配置

CoTracker 节点配置

变量描述默认值
DEVICE推理设备 (cuda/mps/cpu)自动检测
COTRACKER_WINDOW_SIZE追踪帧缓冲区大小16
INTERACTIVE_MODE启用交互模式false
COTRACKER_CHECKPOINT自定义模型检查点路径None

相机节点配置

变量描述默认值
CAPTURE_PATH相机设备索引或视频路径0
IMAGE_WIDTH捕获宽度640
IMAGE_HEIGHT捕获高度480
ENCODING图像编码 (rgb8/bgr8)rgb8

数据流变体

  • facebook_cotracker.yml:使用 YOLO 进行物体检测 + CoTracker 进行追踪
  • qwenvl_cotracker.yml:使用 Qwen2.5-VL(视觉语言模型)进行检测 + CoTracker 进行追踪

架构

YOLO + CoTracker 流水线

+--------+     +------+     +-----------+     +--------+
|  相机  | --> | YOLO | --> | CoTracker | --> | Rerun  |
+--------+     +------+     +-----------+     +--------+
     |                            ^
     |____________________________|
              (图像流)

VLM + CoTracker 流水线

+--------+     +---------+     +------------+     +-----------+     +--------+
|  相机  | --> | Qwen-VL | --> | parse_bbox | --> | CoTracker | --> | Rerun  |
+--------+     +---------+     +------------+     +-----------+     +--------+
     |                                                   ^
     |___________________________________________________|
                        (图像流)

工作原理

  1. 物体检测:YOLO(或 VLM)检测每帧中的物体并输出边界框
  2. 点生成:CoTracker 将边界框转换为追踪点(每个框 5 个点)
  3. 点追踪:CoTracker 使用深度学习在连续帧之间追踪这些点
  4. 可视化:追踪点绘制在帧上并在 Rerun 中显示

故障排除

相机问题

  • 检查系统相机权限
  • 验证 CAPTURE_PATH 中的相机设备索引是否正确
  • 首先在其他应用程序中测试相机

模型下载缓慢

  • 首次运行需要下载 CoTracker 和 YOLO 模型,可能需要一些时间
  • 确保网络连接稳定
  • 模型在首次下载后会被缓存

GPU 内存问题

  • 减小 IMAGE_WIDTHIMAGE_HEIGHT 以降低内存使用
  • 设置 DEVICE=cpu 使用 CPU(较慢但内存占用较少)
  • 减小 COTRACKER_WINDOW_SIZE 以减少帧缓冲

Rerun 版本不匹配

  • 如果看到版本警告,请安装匹配的 Rerun SDK:
    pip install rerun-sdk==<version>
    

源码

完整源码请参考:dora-examples/tracker

翻译

概述

此数据流创建实时语音翻译流水线:

麦克风 -> VAD -> Whisper (STT) -> 翻译 -> Rerun (显示)

流水线从麦克风捕获音频,检测语音活动,使用 Whisper 转录语音,翻译成另一种语言,并在 Rerun 查看器中显示结果。

节点

  • dora-microphone:从麦克风捕获音频
  • dora-vad:语音活动检测 - 检测您何时在说话
  • dora-distil-whisper:使用 Distil-Whisper 模型进行语音转文字
  • dora-argotranslate:使用 Argos Translate 进行离线翻译
  • dora-phi4:使用 Microsoft Phi-4 进行多模态翻译(替代方案)
  • dora-rerun:在 Rerun 查看器中可视化转录和翻译结果
  • dora-kokoro-tts:翻译输出的文字转语音(可选)
  • dora-pyaudio:TTS 音频输出(可选)

先决条件

  • Python 3.11+
  • dora-rs
  • 麦克风
  • uv(Python 包管理器)
  • Phi-4 推荐使用 GPU(flash-attn 需要 CUDA)

快速开始

1. 安装 dora

# 安装 dora CLI
cargo install dora-cli

# 或安装 Python 包(必须与 CLI 版本匹配)
pip install dora-rs

2. 构建和运行

使用 Phi-4(多模态翻译)

cd examples/translation

# 创建虚拟环境
uv venv --seed -p 3.11

# 构建数据流
dora build phi4-dev.yml --uv

# 运行数据流
dora run phi4-dev.yml --uv

# 开始用英语、中文、德语、法语、意大利语、日语、西班牙语或葡萄牙语说话

使用 Argos Translate(离线翻译)

cd examples/translation

# 创建虚拟环境
uv venv --seed -p 3.11

# 构建英语到中文翻译
dora build dataflow_en_zh.yml --uv

# 运行数据流
dora run dataflow_en_zh.yml --uv

3. 查看结果

# 连接到 Rerun 查看器
rerun --connect rerun+http://127.0.0.1:9876/proxy

配置

Whisper 节点配置

变量描述默认值
TARGET_LANGUAGE口语输入的语言english
TRANSLATE启用 Whisper 翻译false

Argos Translate 配置

变量描述默认值
SOURCE_LANGUAGE源语言代码(如 en、zh、fr)必填
TARGET_LANGUAGE目标语言代码(如 en、zh、fr)必填

Phi-4 配置

变量描述默认值
LEAD_MODALITY主要输入模态audio

数据流变体

Argos Translate 流水线

  • dataflow_en_zh.yml:英语到中文
  • dataflow_zh_en.yml:中文到英语
  • dataflow_en_fr.yml:英语到法语
  • dataflow_fr_en.yml:法语到英语
  • dataflow_en_zh_terminal.yml:英语到中文(终端输出)
  • dataflow_zh_en_terminal.yml:中文到英语(终端输出)
  • dataflow_en_zh_terminal_argo.yml:英语到中文(终端显示)

Phi-4 流水线

  • phi4-dev.yml:带 TTS 输出的多模态翻译(支持 8+ 种语言)

架构

Argos Translate 流水线

+------------+     +---------+     +------------------+     +------------------+
|   麦克风   | --> |   VAD   | --> | distil-whisper   | --> | argos-translate  |
+------------+     +---------+     | (语音转文字)     |     | (翻译)           |
                                   +------------------+     +------------------+
                                                                    |
                                                                    v
                                                               +--------+
                                                               | rerun  |
                                                               | (显示) |
                                                               +--------+

Phi-4 流水线(带 TTS)

+------------+     +---------+     +------------------+     +------------------+
|   麦克风   | --> |   VAD   | --> |     Phi-4        | --> |   kokoro-tts     |
+------------+     +---------+     | (多模态 AI)      |     | (文字转语音)     |
                                   +------------------+     +------------------+
                                            |                        |
                                            v                        v
                                       +--------+              +-----------+
                                       | rerun  |              | pyaudio   |
                                       | (显示) |              | (扬声器)  |
                                       +--------+              +-----------+

支持的语言

Argos Translate

  • 英语 (en)
  • 中文 (zh)
  • 法语 (fr)
  • 德语 (de)
  • 西班牙语 (es)
  • 意大利语 (it)
  • 葡萄牙语 (pt)
  • 以及更多…

Phi-4 多模态

  • 英语
  • 中文
  • 德语
  • 法语
  • 意大利语
  • 日语
  • 西班牙语
  • 葡萄牙语

故障排除

麦克风问题

  • 检查系统麦克风权限
  • 验证是否选择了正确的音频输入设备
  • 首先在其他应用程序中测试麦克风

模型下载缓慢

  • 首次运行需要下载 Whisper 和翻译模型,可能需要一些时间
  • 确保网络连接稳定
  • 模型在首次下载后会被缓存

Phi-4 Flash Attention 错误

  • flash-attn 需要 CUDA 和 Linux
  • 安装命令:pip install flash-attn --no-build-isolation
  • 对于非 CUDA 系统,请使用 Argos Translate 流水线

Argos 语言包未找到

  • 安装语言包:argospm install translate-en_zh
  • 检查可用包:argospm search

Rerun 版本不匹配

  • 如果看到版本警告,请安装匹配的 Rerun SDK:
    pip install rerun-sdk==<version>
    

源码

完整源码请参考:dora-examples/translation

视觉语言模型 (VLM) 示例

概述

此数据流使用 Qwen2.5-VL 创建视觉语言交互管道:

相机 -> Qwen2.5-VL -> Rerun (显示)

该管道从相机捕获视频,使用视觉语言模型处理图像以理解和描述所见内容,并在 Rerun 查看器中显示结果。它还可以集成语音功能,实现完整的多模态体验。

节点

  • opencv-video-capture:从相机捕获视频
  • dora-qwen2-5-vl:视觉语言模型 (Qwen2.5-VL) 用于图像理解
  • dora-qwenvl:原始 QwenVL 模型(备选)
  • dora-rerun:可视化相机画面和 VLM 响应
  • dora-microphone:捕获语音输入的音频(可选)
  • dora-vad:语音活动检测(可选)
  • dora-distil-whisper:语音转文字,用于语音提问(可选)
  • dora-kokoro-tts:文字转语音,用于语音回复(可选)
  • dora-pyaudio:TTS 音频输出(可选)

前置条件

  • Python 3.11+
  • dora-rs
  • 相机(网络摄像头)
  • uv(Python 包管理器)
  • 推荐使用 GPU(CUDA/MPS 可加速推理)

快速开始

1. 安装 dora

# 安装 dora CLI
cargo install dora-cli

# 或安装 Python 包(必须与 CLI 版本匹配)
pip install dora-rs

2. 构建和运行

仅视觉模式(简单)

cd examples/vlm

# 创建虚拟环境
uv venv --seed -p 3.11

# 构建数据流
dora build qwen2-5-vl-vision-only-dev.yml --uv

# 运行数据流
dora run qwen2-5-vl-vision-only-dev.yml --uv

语音到语音模式(完整)

cd examples/vlm

# 创建虚拟环境
uv venv --seed -p 3.11

# 构建数据流
dora build qwenvl.yml --uv

# 运行数据流
dora run qwenvl.yml --uv

无需克隆仓库

uv venv -p 3.11 --seed
dora build https://raw.githubusercontent.com/dora-rs/dora/main/examples/vlm/qwenvl.yml --uv
dora run https://raw.githubusercontent.com/dora-rs/dora/main/examples/vlm/qwenvl.yml --uv

3. 查看结果

# 连接到 Rerun 查看器
rerun --connect rerun+http://127.0.0.1:9876/proxy

配置

相机节点配置

变量描述默认值
CAPTURE_PATH相机设备索引或视频路径0
IMAGE_WIDTH捕获宽度640
IMAGE_HEIGHT捕获高度480

VLM 节点配置

变量描述默认值
DEFAULT_QUESTION关于图像的提问Describe the image in three words.
IMAGE_RESIZE_RATIO输入图像的缩放比例1.0
USE_MODELSCOPE_HUB使用 ModelScope 代替 HuggingFacefalse

Whisper 节点配置

变量描述默认值
TARGET_LANGUAGE语音识别语言english

数据流变体

仅视觉

  • qwen2-5-vl-vision-only-dev.yml:相机 + Qwen2.5-VL + Rerun(简单视觉模式)

语音到语音

  • qwenvl.yml:使用 QwenVL + OuteTTS 的完整管道,支持语音输入/输出
  • qwen2-5-vl-speech-to-speech-dev.yml:使用 Qwen2.5-VL + Kokoro TTS 的完整管道
  • qwenvl-dev.yml:使用本地节点路径的开发版本

架构

仅视觉管道

+--------+     +-------------+     +--------+
| 相机   | --> | Qwen2.5-VL  | --> | Rerun  |
+--------+     | (VLM)       |     | (显示) |
               +-------------+     +--------+

语音到语音管道

+------------+     +---------+     +---------+
|   麦克风   | --> |   VAD   | --> | Whisper |
+------------+     +---------+     | (STT)   |
                                   +---------+
                                        |
                                        v
+--------+     +-------------+     +---------+     +--------+
| 相机   | --> | Qwen2.5-VL  | <-- |  问题   |     | Rerun  |
+--------+     | (VLM)       |     +---------+     | (显示) |
               +-------------+                     +--------+
                    |                                  ^
                    v                                  |
               +---------+     +---------+             |
               | Kokoro  | --> | PyAudio |-------------+
               | (TTS)   |     | (扬声器)|
               +---------+     +---------+

功能特性

  • 实时视觉理解:描述场景、识别物体、读取文字
  • 语音交互:使用语音询问相机所见内容
  • 语音回复:通过文字转语音听取 VLM 的回答
  • 可定制提示:配置默认问题用于自动分析
  • 多模型支持:可选择 Qwen2.5-VL 或原始 QwenVL

应用场景

  • 无障碍辅助:为视障用户描述周围环境
  • 质量检测:带语音反馈的自动化视觉检测
  • 互动演示:语音控制的图像分析
  • 机器人:自主系统的视觉理解
  • 教育:视觉内容的交互式学习

故障排除

相机问题

  • 检查系统相机权限
  • 验证 CAPTURE_PATH 中的相机设备索引是否正确
  • 先在其他应用中测试相机

模型下载慢

  • 首次运行需要下载可能数 GB 的 VLM 模型
  • 确保网络连接稳定
  • 模型在首次下载后会被缓存
  • 在中国可使用 USE_MODELSCOPE_HUB=true 加速下载

GPU 内存问题

  • Qwen2.5-VL 需要较大的 GPU 内存
  • 减小 IMAGE_RESIZE_RATIO 以降低内存使用
  • 如有可用,使用较小的模型变体

麦克风问题(语音到语音)

  • 检查系统麦克风权限
  • 验证是否选择了正确的音频输入设备
  • 先在其他应用中测试麦克风

Rerun 版本不匹配

  • 如果看到版本警告,安装匹配的 Rerun SDK:
    pip install rerun-sdk==<version>
    

源码

场景应用

DORA-RS Lebai 机械臂驱动

用于控制Lebai LM3机械臂的DORA-RS驱动节点。该驱动通过DORA数据流接收目标关节角度和笛卡尔位姿,并据此控制机器人。

前置条件

1. Lebai L-Master Docker(仿真器)

启动Lebai仿真器:

docker run -d --name lebai-master \
  -p 80:80 \
  -p 5180:5180 \
  -p 5181:5181 \
  lebai/lmaster:latest

打开以下链接验证仿真器是否运行:http://localhost/dashboard

2. 安装Python依赖

重要:dora-rs Python包版本必须与dora-cli版本完全匹配。

pip install -r requirements.txt

# 验证版本是否匹配
dora --version        # 应显示 0.3.11
pip show dora-rs      # 应显示 0.3.11

项目结构

lebai/
├── lebai_driver_node.py   # 主DORA驱动节点
├── goal_publisher_node.py # 用于测试的目标发布节点示例
├── dataflow.yml           # DORA数据流配置
├── requirements.txt       # Python依赖
├── LM3_test.py           # 原始独立测试脚本
└── README.md

使用方法

快速开始

  1. 启动Lebai仿真器(参见前置条件)

  2. 运行DORA数据流:

dora up
dora start dataflow.yml

运行后,你应该能在仿真器中看到机械臂运动:

Lebai仿真器界面

  1. 查看日志:
dora logs lebai_driver
  1. 停止数据流:
dora stop
dora destroy

单独运行节点

用于开发/测试,可直接运行节点:

# 终端1:启动DORA守护进程
dora up

# 终端2:启动数据流
dora start dataflow.yml

# 或独立运行进行测试
python lebai_driver_node.py

节点接口

输入

输入ID格式描述
target_jointsJSON目标关节角度(弧度)
target_poseJSON目标笛卡尔位姿
commandString控制命令

target_joints 格式

简单数组:

[0.0, -1.0, 1.0, 0.0, 1.57, 0.0]

带参数:

{
  "joints": [0.0, -1.0, 1.0, 0.0, 1.57, 0.0],
  "acceleration": 0.6,
  "velocity": 0.3,
  "wait": true
}

target_pose 格式

{
  "x": 0.3,
  "y": 0.0,
  "z": 0.4,
  "rx": 3.14,
  "ry": 0.0,
  "rz": 0.0
}

命令

命令描述
start连接/重新连接机器人
stop断开机器人连接
home移动到初始位置
get_joints获取当前关节位置

输出

输出ID格式描述
current_jointsJSON数组当前关节位置(弧度)
statusStringidlemovingcompletederrorstopped
errorJSON状态为error时的错误详情

配置

环境变量

dataflow.yml中设置或运行前导出:

变量默认值描述
LEBAI_IP127.0.0.1机器人/仿真器IP地址
LEBAI_SIMULATIONtrue真实机器人设为false
LEBAI_ACCELERATION0.6默认加速度(rad/s^2)
LEBAI_VELOCITY0.3默认速度(rad/s)

示例:真实机器人配置

nodes:
  - id: lebai_driver
    path: lebai_driver_node.py
    inputs:
      target_joints: planner/joints
    outputs:
      - current_joints
      - status
      - error
    env:
      LEBAI_IP: "192.168.1.100"    # 你的机器人IP
      LEBAI_SIMULATION: "false"    # 真实机器人模式
      LEBAI_ACCELERATION: "0.4"    # 为安全起见降低速度
      LEBAI_VELOCITY: "0.2"

集成示例

与运动规划器集成

nodes:
  - id: motion_planner
    path: your_planner.py
    inputs:
      goal: user_input/goal
    outputs:
      - joints

  - id: lebai_driver
    path: lebai_driver_node.py
    inputs:
      target_joints: motion_planner/joints
    outputs:
      - current_joints
      - status

与视觉系统集成

nodes:
  - id: camera
    path: camera_node.py
    outputs:
      - image

  - id: vision
    path: vision_node.py
    inputs:
      image: camera/image
    outputs:
      - target_pose

  - id: lebai_driver
    path: lebai_driver_node.py
    inputs:
      target_pose: vision/target_pose
    outputs:
      - status

故障排除

连接失败

  1. 检查仿真器/机器人是否运行:

    curl http://localhost/dashboard
    
  2. 验证端口映射(Docker):

    docker ps
    docker logs lebai-master
    
  3. 检查环境变量中的IP地址

运动不执行

  1. 在仪表板中检查机器人状态
  2. 确保机器人已启用(调用了start_sys)
  3. 检查输出中的错误:
    dora logs lebai_driver
    

DORA无法启动

  1. 确保DORA守护进程正在运行:

    dora up
    
  2. 检查数据流语法:

    dora check dataflow.yml
    

节点初始化错误

如果看到RuntimeError: Could not initiate node from environment variableinvalid type: map, expected a YAML tag starting with '!'

  1. 版本不匹配 - dora-rs Python包版本必须与dora-cli匹配:

    # 检查版本
    dora --version
    pip show dora-rs
    
    # 安装匹配版本修复
    pip install dora-rs==0.3.11  # 匹配你的CLI版本
    
  2. 修复后重启DORA守护进程

    dora destroy
    dora up
    dora start dataflow.yml
    

源码

完整源码请参考:dora-examples/lebai

DORA-RS SO-101 Follower Arm Driver (MuJoCo Simulation)

A DORA-RS driver node for controlling the SO-101 follower arm using MuJoCo physics simulation. Uses the official SO-ARM100 model from TheRobotStudio.

The SO-101 is a 6-DOF low-cost robot arm commonly used in the LeRobot teleoperation project.

Features

  • Official SO-ARM100 MuJoCo model with accurate CAD meshes
  • 6-DOF control (5 arm joints + gripper)
  • Smooth quintic trajectory interpolation
  • OpenCV-based visualization (works on macOS without mjpython)
  • DORA dataflow integration

Prerequisites

1. Install DORA-RS

Install the DORA CLI:

# Using cargo (recommended)
cargo install dora-cli

# Check version
dora --version

2. Install Python Dependencies

IMPORTANT: The dora-rs Python package version must match the dora-cli version exactly.

pip install -r requirements.txt

# Verify versions match
dora --version        # Note the version
pip show dora-rs      # Should match CLI version

Project Structure

so101/
├── so101_driver_node.py   # Main DORA driver node with MuJoCo simulation
├── goal_publisher_node.py # Example goal publisher for testing
├── dataflow.yml           # DORA dataflow configuration
├── requirements.txt       # Python dependencies
├── so101_new_calib.xml    # MuJoCo model (from SO-ARM100)
├── scene.xml              # Scene configuration
├── assets/                # STL mesh files
├── README.md
└── RELEASE.md

Usage

Quick Start

  1. Run the DORA dataflow:
cd so101
dora up
dora start dataflow.yml
  1. Monitor the logs:
dora logs so101_driver
  1. Stop the dataflow:
dora stop
dora destroy

Node Interfaces

Inputs

Input IDFormatDescription
target_jointsJSONTarget joint angles for all 6 joints
commandStringControl commands

target_joints Format

Simple array (6 values):

[0.0, 0.5, -0.8, 0.3, 0.0, 1.0]

With parameters:

{
  "joints": [0.0, 0.5, -0.8, 0.3, 0.0, 1.0],
  "duration": 1.5
}

Joint Descriptions

IndexNameDescriptionRange (rad)
0shoulder_panBase rotation-1.92 to 1.92
1shoulder_liftShoulder pitch-1.75 to 1.75
2elbow_flexElbow pitch-1.69 to 1.69
3wrist_flexWrist pitch-1.66 to 1.66
4wrist_rollWrist roll-2.74 to 2.84
5gripperGripper-0.17 to 1.75

Commands

CommandDescription
startInitialize simulation
stopClose simulation
homeMove to home position
get_jointsGet current joint positions

Outputs

Output IDFormatDescription
current_jointsJSON arrayCurrent joint positions
statusStringidle, moving, completed, error, stopped
errorJSONError details when status is error

Configuration

Environment Variables

Set these in dataflow.yml or export before running:

VariableDefaultDescription
SO101_SHOW_VIEWERtrueShow OpenCV visualization window
SO101_TIMESTEP0.002Simulation timestep (seconds)
SO101_CONTROL_FREQ50Control loop frequency (Hz)

Integration Examples

With LeRobot Teleoperation

nodes:
  - id: leader_arm
    path: leader_arm_node.py
    outputs:
      - joint_positions

  - id: so101_driver
    path: so101_driver_node.py
    inputs:
      target_joints: leader_arm/joint_positions
    outputs:
      - current_joints
      - status

With Policy Inference

nodes:
  - id: camera
    path: camera_node.py
    outputs:
      - image

  - id: policy
    path: policy_node.py
    inputs:
      image: camera/image
      current_joints: so101_driver/current_joints
    outputs:
      - action

  - id: so101_driver
    path: so101_driver_node.py
    inputs:
      target_joints: policy/action
    outputs:
      - current_joints
      - status

Troubleshooting

Viewer Not Showing

The driver uses OpenCV for rendering, which works with regular Python on macOS:

# In dataflow.yml - ensure viewer is enabled
env:
  SO101_SHOW_VIEWER: "true"

Model Not Found

Ensure all files are present:

  • so101_new_calib.xml - Main model file
  • assets/ directory with all STL meshes

DORA Not Starting

  1. Ensure DORA daemon is running:

    dora up
    
  2. Check dataflow syntax:

    dora check dataflow.yml
    

Model Credits

The SO-101 model is from the SO-ARM100 project by TheRobotStudio, generated using the onshape-to-robot plugin.

License

MIT License

远程

Franka Panda 机械臂驱动

用于控制 Franka Panda 机械臂的 DORA-RS 驱动节点。此驱动使用 PyBullet 进行仿真,并通过 DORA 数据流接受目标关节角度和笛卡尔位姿。

功能特性

  • Franka Panda 机器人 7 自由度关节控制
  • 带逆运动学的笛卡尔位姿控制
  • 夹爪控制(开/关)
  • PyBullet 物理仿真(可选 GUI)
  • 兼容真实 Franka 机器人(需要 libfranka)

先决条件

1. 安装 DORA-RS

安装 DORA CLI:

cargo install dora-cli

# 检查版本
dora --version

2. 安装 Python 依赖

重要:dora-rs Python 包版本必须与 dora-cli 版本完全匹配。

pip install -r requirements.txt

# 验证版本匹配
dora --version        # 检查 CLI 版本
pip show dora-rs      # 应与 CLI 版本匹配

项目结构

franka/
├── franka_driver_node.py   # 主 DORA 驱动节点(PyBullet 仿真)
├── goal_publisher_node.py  # 测试用目标发布器示例
├── dataflow.yml            # DORA 数据流配置
├── requirements.txt        # Python 依赖
└── README.md

使用方法

快速开始

  1. 运行 DORA 数据流:
dora up
dora start dataflow.yml

Franka Panda 仿真

  1. 监控日志:
dora logs franka_driver
  1. 停止数据流:
dora stop
dora destroy

使用 GUI 运行

在 dataflow.yml 中设置 FRANKA_GUI: "true" 以查看 PyBullet 可视化:

env:
  FRANKA_GUI: "true"

节点接口

输入

输入 ID格式描述
target_jointsJSON目标关节角度(7 个值),单位:弧度
target_poseJSON目标笛卡尔位姿
commandString控制命令
gripperString/Float夹爪命令

target_joints 格式

简单数组:

[0.0, -0.785, 0.0, -2.356, 0.0, 1.571, 0.785]

带参数:

{
  "joints": [0.0, -0.785, 0.0, -2.356, 0.0, 1.571, 0.785],
  "velocity": 0.3,
  "wait": true
}

target_pose 格式

{
  "x": 0.4,
  "y": 0.0,
  "z": 0.5,
  "rx": 3.14,
  "ry": 0.0,
  "rz": 0.0
}

命令

命令描述
start连接到仿真
stop断开仿真连接
home移动到初始位置
get_joints获取当前关节位置
get_pose获取当前末端执行器位姿

夹爪命令

命令描述
open打开夹爪(0.04m 宽度)
close关闭夹爪(0.0m 宽度)
0.0-0.04设置特定手指宽度

输出

输出 ID格式描述
current_jointsJSON 数组当前 7 个关节位置,单位:弧度
current_poseJSON 对象当前末端执行器位姿
statusStringidlemovingcompletederrorstopped
errorJSON状态为 error 时的错误详情

配置

环境变量

dataflow.yml 中设置或在运行前导出:

变量默认值描述
FRANKA_SIMULATIONtrue使用 PyBullet 仿真
FRANKA_GUIfalse显示 PyBullet GUI
FRANKA_TIME_STEP0.001仿真时间步长
FRANKA_MAX_VELOCITY0.5最大关节速度(rad/s)
FRANKA_MAX_FORCE240.0最大关节力(N)

Franka Panda 规格

关节限位(弧度)

关节下限上限
J1-2.89732.8973
J2-1.76281.7628
J3-2.89732.8973
J4-3.0718-0.0698
J5-2.89732.8973
J6-0.01753.7525
J7-2.89732.8973

初始位置

home_position = [0.0, -0.785, 0.0, -2.356, 0.0, 1.571, 0.785]

集成示例

与运动规划器集成

nodes:
  - id: motion_planner
    path: your_planner.py
    inputs:
      goal: user_input/goal
    outputs:
      - joints

  - id: franka_driver
    path: franka_driver_node.py
    inputs:
      target_joints: motion_planner/joints
    outputs:
      - current_joints
      - status

与视觉系统集成

nodes:
  - id: camera
    path: camera_node.py
    outputs:
      - image

  - id: vision
    path: vision_node.py
    inputs:
      image: camera/image
    outputs:
      - target_pose

  - id: franka_driver
    path: franka_driver_node.py
    inputs:
      target_pose: vision/target_pose
    outputs:
      - status

故障排除

PyBullet 无法启动

  1. 确保已安装 pybullet:

    pip install pybullet
    
  2. 检查显示问题(GUI 模式):

    export DISPLAY=:0  # Linux
    

DORA 无法启动

  1. 确保 DORA 守护进程正在运行:

    dora up
    
  2. 检查数据流语法:

    dora check dataflow.yml
    

节点初始化错误

如果看到 RuntimeError: Could not initiate node from environment variable

  1. 版本不匹配 - dora-rs Python 包版本必须与 dora-cli 匹配:

    # 检查版本
    dora --version
    pip show dora-rs
    
    # 安装匹配版本修复
    pip install dora-rs==<version>  # 匹配您的 CLI 版本
    
  2. 修复后重启 DORA 守护进程

    dora destroy
    dora up
    dora start dataflow.yml
    

真实机器人支持

对于真实 Franka Panda 机器人支持,您需要:

  • 安装 libfranka
  • Franka 控制接口(FCI)访问权限
  • 实时内核(推荐)

将 PyBullet 调用替换为 libfranka 调用以控制真实机器人。

源码

完整源码请参考:dora-examples/franka

UR5 机械臂驱动

用于通过 RTDE 协议控制 Universal Robots UR5 机械臂的 DORA-RS 驱动节点。此驱动通过 DORA 数据流接受目标关节角度和笛卡尔位姿,并相应地控制机器人。

功能特性

  • 纯 Python RTDE 实现(无原生依赖)
  • 支持 Apple Silicon(M1/M2/M3/M4)Mac
  • 支持 URSim Docker 仿真器和真实 UR5 机器人
  • 关节空间(moveJ)和笛卡尔空间(moveL)运动

先决条件

1. URSim Docker(仿真器)

启动 Universal Robots 仿真器(URSim):

# Apple Silicon(M1/M2/M3/M4)- 需要 Rosetta
docker run -d --name ursim \
  -e ROBOT_MODEL=UR5 \
  -p 5900:5900 \
  -p 6080:6080 \
  -p 29999:29999 \
  -p 30001-30004:30001-30004 \
  --platform=linux/amd64 \
  universalrobots/ursim_e-series

# Intel Mac / Linux
docker run -d --name ursim \
  -e ROBOT_MODEL=UR5 \
  -p 5900:5900 \
  -p 6080:6080 \
  -p 29999:29999 \
  -p 30001-30004:30001-30004 \
  universalrobots/ursim_e-series

访问仿真器:

  • VNC 查看器:localhost:5900(密码:easybot
  • 网页浏览器:http://localhost:6080/vnc.html

重要:启动 URSim 后,您必须通过 VNC 完成以下步骤:

  1. 启动机器人:点击红色电源按钮(左下角)-> 点击“ON“ -> 点击“START“
  2. 确认安全配置(仅首次):
    • 进入汉堡菜单(右上角)-> Settings -> System -> Safety
    • 点击底部的“Confirm Safety Configuration“
    • 接受默认配置
  3. 验证机器人模式:机器人应显示绿色的“RUNNING“

2. 安装 DORA-RS

安装 DORA CLI:

cargo install dora-cli

# 检查版本
dora --version

3. 安装 Python 依赖

重要:dora-rs Python 包版本必须与 dora-cli 版本完全匹配。

pip install -r requirements.txt

# 验证版本匹配
dora --version        # 检查 CLI 版本
pip show dora-rs      # 应与 CLI 版本匹配

项目结构

ur5/
├── ur5_driver_node.py     # 主 DORA 驱动节点(纯 Python RTDE)
├── goal_publisher_node.py # 测试用目标发布器示例
├── test_connection.py     # 连接测试脚本
├── dataflow.yml           # DORA 数据流配置
├── requirements.txt       # Python 依赖
└── README.md

使用方法

快速开始

  1. 启动 URSim 仿真器(参见先决条件)

  2. 通过 VNC 在 URSim 中启动机器人

  3. 运行 DORA 数据流:

cd ur5
dora up
dora start dataflow.yml
  1. 监控日志:
dora logs ur5_driver
  1. 停止数据流:
dora stop
dora destroy

节点接口

输入

输入 ID格式描述
target_jointsJSON目标关节角度,单位:弧度
target_poseJSON目标笛卡尔位姿
commandString控制命令

target_joints 格式

简单数组(6 个关节:基座、肩部、肘部、腕1、腕2、腕3):

[0.0, -1.5708, 1.5708, -1.5708, -1.5708, 0.0]

带参数:

{
  "joints": [0.0, -1.5708, 1.5708, -1.5708, -1.5708, 0.0],
  "acceleration": 0.5,
  "velocity": 0.3,
  "wait": true
}

target_pose 格式

{
  "x": 0.3,
  "y": 0.0,
  "z": 0.4,
  "rx": 3.14,
  "ry": 0.0,
  "rz": 0.0
}

命令

命令描述
start连接/重新连接到机器人
stop停止运动并断开连接
home移动到初始位置
get_joints获取当前关节位置
get_pose获取当前 TCP 位姿

输出

输出 ID格式描述
current_jointsJSON 数组当前关节位置,单位:弧度
current_poseJSON 字典当前 TCP 位姿(x, y, z, rx, ry, rz)
statusStringidlemovingcompletederrorstopped
errorJSON状态为 error 时的错误详情

配置

环境变量

dataflow.yml 中设置或在运行前导出:

变量默认值描述
UR5_IP127.0.0.1机器人/仿真器 IP 地址
UR5_ACCELERATION0.5默认加速度(rad/s^2 或 m/s^2)
UR5_VELOCITY0.3默认速度(rad/s 或 m/s)

示例:真实机器人配置

nodes:
  - id: ur5_driver
    path: ur5_driver_node.py
    inputs:
      target_joints: planner/joints
    outputs:
      - current_joints
      - current_pose
      - status
      - error
    env:
      UR5_IP: "192.168.1.100"    # 您的机器人 IP
      UR5_ACCELERATION: "0.3"    # 为安全起见减速
      UR5_VELOCITY: "0.2"

集成示例

与运动规划器集成

nodes:
  - id: motion_planner
    path: your_planner.py
    inputs:
      goal: user_input/goal
    outputs:
      - joints

  - id: ur5_driver
    path: ur5_driver_node.py
    inputs:
      target_joints: motion_planner/joints
    outputs:
      - current_joints
      - status

与视觉系统集成

nodes:
  - id: camera
    path: camera_node.py
    outputs:
      - image

  - id: vision
    path: vision_node.py
    inputs:
      image: camera/image
    outputs:
      - target_pose

  - id: ur5_driver
    path: ur5_driver_node.py
    inputs:
      target_pose: vision/target_pose
    outputs:
      - status

故障排除

连接失败

  1. 检查 URSim 是否正在运行:

    docker ps | grep ursim
    docker logs ursim
    
  2. 验证机器人已在 URSim 中启动(通过 VNC 连接到 localhost:5900

  3. 检查 RTDE 端口是否可访问:

    nc -zv 127.0.0.1 30004
    
  4. 检查环境变量中的 IP 地址

运动未执行

  1. 确保机器人已启动且在 URSim 中释放了制动器
  2. 检查机器人是否处于远程控制模式(真实机器人)
  3. 检查示教器/URSim 中的保护性停止
  4. 检查输出中的错误:
    dora logs ur5_driver
    

DORA 无法启动

  1. 确保 DORA 守护进程正在运行:

    dora up
    
  2. 检查数据流语法:

    dora check dataflow.yml
    

节点初始化错误

如果看到 RuntimeError: Could not initiate node from environment variable

  1. 版本不匹配 - dora-rs Python 包版本必须与 dora-cli 匹配:

    # 检查版本
    dora --version
    pip show dora-rs
    
    # 安装匹配版本修复
    pip install dora-rs==<version>  # 匹配您的 CLI 版本
    
  2. 修复后重启 DORA 守护进程

    dora destroy
    dora up
    dora start dataflow.yml
    

RTDE “Safety Setup Not Confirmed” 错误

如果看到“SafetySetup has not been confirmed yet“错误:

  1. 通过 VNC 连接到 URSim(localhost:5900
  2. 进入 Settings(汉堡菜单)-> System -> Safety
  3. 点击底部的“Confirm Safety Configuration“
  4. 重启驱动

测试连接脚本

运行包含的测试脚本以验证连接:

python test_connection.py

这将测试:

  • Dashboard Server(端口 29999)
  • RTDE 接口(端口 30004)
  • URScript 接口(端口 30002)

RTDE 协议说明

UR RTDE(实时数据交换)协议提供:

  • 500Hz 实时机器人状态数据流
  • 低延迟命令接口
  • 同步和异步运动控制

与其他接口的主要区别:

  • 比主/辅接口更可靠
  • 比 Dashboard Server 延迟更低
  • 直接访问伺服控制

源码

完整源码请参考:dora-examples/ur5

其他样例

基准测试

源码

完整源码请参考:dora-examples/cuda-benchmark

概述

使用 CUDA Zero Copy 代替常规共享内存 (CPU) 的延迟测试示例。

安装

pip install dora-rs-cli # if not already present

# Install pyarrow with gpu support
conda install pyarrow "arrow-cpp-proc=*=cuda" -c conda-forge

## Test installation with
python -c "import pyarrow.cuda"

# Install numba for translation from arrow to torch
pip install numba

## Test installation with
python -c "import numba.cuda"

# Install torch if it's not already present
pip install torch

## Test installation with
python -c "import torch; assert torch.cuda.is_available()"

运行

dora run cpu_bench.yml

dora run cuda_bench.yml

cat benchmark_data.csv

运行演示代码

dora up
dora start demo_bench.yml --detach
python demo_receiver.py
dora destroy

Python Arrow 测试

本文档介绍 dora-rs 中 Apache Arrow 数据格式的使用方法。

什么是 Arrow?

dora-rs 使用 Apache Arrow 作为数据通信格式。Arrow 是一种跨语言的列式内存数据格式,具有以下特点:

  • 零拷贝读取 - 高效的数据传输,无需复制数据
  • 跨语言支持 - Rust、Python、C++ 等语言无缝协作
  • 标准化格式 - 统一的数据表示方式

核心概念

在 Arrow 中,所有数据都是数组。即使是标量值,也必须封装在列表中:

import pyarrow as pa

# 标量值也需要封装为数组
value = pa.array([42])  # 不是 42,而是 [42]

数据类型转换

从 Arrow 数组转换

# 获取 dora 事件中的 Arrow 数组
arrow_array = dora_event["value"]

# 转换为 Python 列表
list_data = arrow_array.to_pylist()

# 转换为 NumPy 数组(零拷贝,只读)
numpy_array = arrow_array.to_numpy()

# 转换为 Pandas Series
pandas_series = arrow_array.to_pandas()

转换为 Arrow 数组

import pyarrow as pa
import numpy as np
import pandas as pd

# 从 Python 列表创建
numeric_array = pa.array([1, 2, 3])

# 从字符串列表创建
string_array = pa.array(["Hello", "World"])

# 从字典/结构体创建
struct_array = pa.array([{"a": 1, "b": 2, "c": [1, 2, 3]}])

# 从 NumPy 数组创建
numpy_array = pa.array(np.array([1, 2, 3]))

# 从 Pandas Series 创建
df = pd.DataFrame({'col1': [1, 2, 3]})
pandas_array = pa.array(df["col1"])

支持的数据类型

数据类型示例说明
数值列表pa.array([1, 2, 3])整数、浮点数
字符串数组pa.array(["Hello"])文本数据
字典/结构体pa.array([{"a": 1}])嵌套数据结构
NumPy 数组pa.array(np.array([1, 2]))科学计算数据
Pandas Seriespa.array(df["col"])数据分析数据

在 dora 节点中使用

发送数据

from dora import Node
import pyarrow as pa

node = Node()

# 发送数值数组
node.send_output("numbers", pa.array([1, 2, 3, 4, 5]))

# 发送字符串
node.send_output("message", pa.array(["Hello from dora!"]))

# 发送图像数据(NumPy 数组)
import numpy as np
image = np.random.randint(0, 255, (480, 640, 3), dtype=np.uint8)
node.send_output("image", pa.array(image.flatten()))

接收数据

from dora import Node

node = Node()

for event in node:
    if event["type"] == "INPUT":
        # 获取 Arrow 数组
        arrow_array = event["value"]

        # 转换为需要的格式
        data = arrow_array.to_numpy()

        # 处理数据...

零拷贝优势

Arrow 的零拷贝特性使得数据传输非常高效:

# 零拷贝读取 - 直接访问内存,不复制数据
numpy_array = arrow_array.to_numpy()  # 只读访问

# 如果需要修改,需要显式复制
numpy_array_copy = arrow_array.to_numpy().copy()  # 可写

最佳实践

  1. 使用原生类型 - 尽量使用 Arrow 原生支持的类型
  2. 批量处理 - 将多个值打包成数组,而非单独发送
  3. 零拷贝 - 尽量使用零拷贝读取,避免不必要的内存分配
  4. 类型一致 - 保持发送和接收端的数据类型一致

源码

完整源码请参考:dora-examples/pyarrow-test

参考文档

附录

词汇表

  • 节点(Node)
  • 算符(Operator)
  • 协作器(Coordinator)

其具体关系请参阅Dora设计

ROS2安装

ROS2安装的详细文档,请以ROS2官方文档为准

locale  # check for UTF-8

sudo apt update && sudo apt install locales
sudo locale-gen en_US en_US.UTF-8
sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
export LANG=en_US.UTF-8

locale  # verify settings

启用需要的仓库

sudo apt install software-properties-common
sudo add-apt-repository universe

sudo apt update && sudo apt install curl -y
export ROS_APT_SOURCE_VERSION=$(curl -s https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest | grep -F "tag_name" | awk -F\" '{print $4}')
curl -L -o /tmp/ros2-apt-source.deb "https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.$(. /etc/os-release && echo $VERSION_CODENAME)_all.deb" # If using Ubuntu derivates use $UBUNTU_CODENAME
sudo dpkg -i /tmp/ros2-apt-source.deb

安装相应包

sudo apt install ros-jazzy-desktop
# or sudo apt install ros-jazzy-desktop

教程

欢迎来到全新开启的Dora on Windows11实践教程!本教程将帮助你从零开始学习如何使用 DORA 构建机器人应用。 该教程面向新手,但是需要对Windows11操作系统有一定的了解。

目录

  1. 安装 - 安装 DORA CLI 和依赖
  2. 示例Echo - 安装 DORA CLI 和依赖

安装

基础环境

操作系统:Windows 11系统

终端:我们的教程使用的终端都是PowerShell,不是CMD,也不是WSL。

我这里使用的是当前最新的版本:1.23.13503.0

查看版本命令:$PSVersionTable.PSVersion

PS E:\projects\Dora> $PSVersionTable.PSVersion

Major  Minor  Patch  PreReleaseLabel BuildLabel
-----  -----  -----  --------------- ----------
7      5      4

PS E:\projects\Dora> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      7.5.4
PSEdition                      Core
GitCommitId                    7.5.4
OS                             Microsoft Windows 10.0.26200
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

如果你还没有最新版的PowerShell,在Microsoft Store中进行下载或更新。

安装 Rustup

Dora 是基于 Rust 开发的,安装 Dora 之前,先安装 Rust 环境。

Rustup 是 Rust 官方的跨平台 Rust 安装工具,同时提供了 Rust 版本管理能力。

要将程序编译为 exe 文件,Rust 需要一个链接器、库和 Windows API 导入库。需要安装 Visual Studio。

如果你还没有安装 Visual Studio,可以使用自动安装,那么 rustup-init 将会提供自动安装前置条件的选项。它会安装 Visual Studio Community 版,该版本对个人、学术及开源用途是免费的,非常合适。如果你希望根据自己的 Visual Studio 来安装,可以参考 https://rust-lang.github.io/rustup/installation/windows-msvc.html 完整的安装说明。

https://rustup.rs/ 下载 rustup-init.exe

如果你想自定义安装位置,可以在执行之前设置环境变量。

# ==========================================================
# Rust 全家桶环境变量配置脚本 (2026 更新版)
# 参考:https://rust-lang.github.io/rustup/environment-variables.html
# ==========================================================

# --- 1. 基础路径定义 ---
$baseDir = "E:\Dev\SDK"
$rustupHome = Join-Path $baseDir "Rustup"
$cargoHome  = Join-Path $baseDir "Cargo"
$cargoBin   = Join-Path $cargoHome "bin"

# --- 2. 核心存储路径 ---
[Environment]::SetEnvironmentVariable("RUSTUP_HOME", $rustupHome, "User")
[Environment]::SetEnvironmentVariable("CARGO_HOME", $cargoHome, "User")

# --- 3. 性能与行为优化 (根据最新文档新增) ---

# [网络] 如果你在国内,建议取消下面两行的注释以使用字节跳动或清华镜像,加快下载速度
# [Environment]::SetEnvironmentVariable("RUSTUP_DIST_SERVER", "https://rsproxy.cn", "User")
# [Environment]::SetEnvironmentVariable("RUSTUP_UPDATE_ROOT", "https://rsproxy.cn/rustup", "User")

# [并发] 增加并发下载数(默认随组件数,强制指定可提高稳定性)
[Environment]::SetEnvironmentVariable("RUSTUP_CONCURRENT_DOWNLOADS", "4", "User")

# [IO/线程] 设置 IO 线程数,提升解压速度 (最大 8)
[Environment]::SetEnvironmentVariable("RUSTUP_IO_THREADS", "8", "User")

# [内存] 解压时允许使用的最大 RAM (单位: 字节),此处设为 1GB
[Environment]::SetEnvironmentVariable("RUSTUP_UNPACK_RAM", "1073741824", "User")

# [自动安装] 默认开启。如果运行未安装的工具链命令,rustup 会自动下载
[Environment]::SetEnvironmentVariable("RUSTUP_AUTO_INSTALL", "1", "User")

# [超时] 增加下载超时时间到 300 秒 (默认 180),防止网络波动导致中断
[Environment]::SetEnvironmentVariable("RUSTUP_DOWNLOAD_TIMEOUT", "300", "User")

# --- 4. 界面与反馈 ---
# 强制显示彩色输出和进度条
[Environment]::SetEnvironmentVariable("RUSTUP_TERM_COLOR", "always", "User")
[Environment]::SetEnvironmentVariable("RUSTUP_TERM_PROGRESS_WHEN", "always", "User")

# --- 5. 安全地更新系统 Path ---
$oldPath = [Environment]::GetEnvironmentVariable("Path", "User")
if ($oldPath -notlike "*$cargoBin*") {
    $cleanPath = if ([string]::IsNullOrWhiteSpace($oldPath)) { "" } else { $oldPath.TrimEnd(';') }
    $newPath = $cleanPath + ";" + $cargoBin
    [Environment]::SetEnvironmentVariable("Path", $newPath, "User")
    Write-Host "✅ Path 已更新,指向: $cargoBin" -ForegroundColor Green
} else {
    Write-Host "ℹ️ Path 中已存在 Cargo 路径,跳过更新。" -ForegroundColor Cyan
}

Write-Host "`n🚀 Rust 环境变量配置完成!请重启终端(如 PowerShell/CMD)使设置生效。" -ForegroundColor Yellow

执行 rustup-init.exe 命令开始安装。

PS C:\Users\dora> rustup-init.exe

重新启动终端,验证 Rustup 安装。

PS C:\Users\dora> rustup -V
rustup 1.28.2 (e4f3ad6f8 2025-04-28)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
info: No `rustc` is currently active

使用 rustup default stable 命令安装默认版本的 Rust。

PS C:\Users\dora> rustup default stable
info: syncing channel updates for 'stable-x86_64-pc-windows-msvc'
763.9 KiB / 1012.7 KiB ( 75 %)  17.8 KiB/s in  1m 45s ETA: 13s
error: could not download file from 'https://static.rust-lang.org/dist/channel-rust-stable.toml' to 'C:\Users\Miao\.rustup\tmp\u71xqzsnptzibr6m_file.toml': error decoding response body: request or response body error: operation timed out
PS C:\Users\dora> rustup default stable
info: syncing channel updates for 'stable-x86_64-pc-windows-msvc'
1012.7 KiB / 1012.7 KiB (100 %)  15.6 KiB/s in  2m 22s
info: latest update on 2025-12-11, rust version 1.92.0 (ded5c06cf 2025-12-08)
info: downloading component 'cargo'
  9.4 MiB /   9.4 MiB (100 %)   1.3 MiB/s in 31s
...
info: installing component 'rustc'
 68.6 MiB /  68.6 MiB (100 %)  24.6 MiB/s in  2s
info: installing component 'rustfmt'
info: default toolchain set to 'stable-x86_64-pc-windows-msvc'

  stable-x86_64-pc-windows-msvc installed - rustc 1.92.0 (ded5c06cf 2025-12-08)

完成后确认安装是否成功。

PS C:\Users\dora> rustup default stable
info: using existing install for 'stable-x86_64-pc-windows-msvc'
info: default toolchain set to 'stable-x86_64-pc-windows-msvc'

  stable-x86_64-pc-windows-msvc unchanged - rustc 1.92.0 (ded5c06cf 2025-12-08)
PS C:\Users\dora> rustc -V
rustc 1.92.0 (ded5c06cf 2025-12-08)
PS C:\Users\dora> cargo -V
cargo 1.92.0 (344c4567c 2025-10-21)

安装 uv

必要步骤。

uv 是使用 Rust 构建的一款高性能 Python 版本管理工具。

uv 源码仓库:https://github.com/astral-sh/uv

我们已经安装了 Rust,所以使用 cargo 进行安装:

PS C:\Users\dora> rustup default stable
info: using existing install for 'stable-x86_64-pc-windows-msvc'
info: default toolchain set to 'stable-x86_64-pc-windows-msvc'

  stable-x86_64-pc-windows-msvc unchanged - rustc 1.92.0 (ded5c06cf 2025-12-08)

PS C:\Users\dora> cargo install --locked uv
    Updating crates.io index
  Downloaded uv v0.9.24
  Downloaded 1 crate (2.0MiB) in 4.38s
  Installing uv v0.9.24
    Updating crates.io index
    Updating crates.io index
  Downloaded adler2 v2.0.1
...
   Compiling uv-requirements v0.0.13
    Finished `release` profile [optimized] target(s) in 3m 52s
  Installing E:\Dev\SDK\Cargo\bin\uv.exe
  Installing E:\Dev\SDK\Cargo\bin\uvx.exe
   Installed package `uv v0.9.24` (executables `uv.exe`, `uvx.exe`)

PS C:\Users\dora> uv -V
uv 0.9.24

PS C:\Users\dora> Get-Command uv
CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Application     uv.exe                                             0.0.0.0    E:\Dev\SDK\Cargo\bin\uv.exe

PS C:\Users\dora>

如果想自定义安装位置,可以修改以下环境变量再安装:

# ==========================================================
# UV 全家桶环境变量配置脚本 (基于 0.9.x+ 文档)
# https://docs.astral.sh/uv/reference/environment/
# 目标:将所有下载、缓存、Python解释器及工具锁定在非系统盘
# ==========================================================

# 1. 定义基础路径
$baseDir = "E:\Dev\SDK\uv"

# 2. 定义变量映射 (严格对照官方文档)
$envMap = @{
    # uv 程序本身的安装位置 (uv self update 也会更新到这里)
    "UV_INSTALL_DIR"         = "$baseDir\bin"
    
    # 全局缓存(Wheels, 源文件, 索引缓存等)- 占用空间最大
    "UV_CACHE_DIR"           = "$baseDir\cache"
    
    # 已经解压安装好的 Python 解释器存放地
    "UV_PYTHON_INSTALL_DIR"  = "$baseDir\python"
    
    # 下载 Python 安装包压缩包时的临时存放地 (防止占用C盘Temp)
    "UV_PYTHON_CACHE_DIR"    = "$baseDir\python-cache"
    
    # 通过 'uv tool install' 安装的工具虚拟环境位置
    "UV_TOOL_DIR"            = "$baseDir\tools"
    
    # 工具的可执行文件快捷方式存放地
    "UV_TOOL_BIN_DIR"        = "$baseDir\tools-bin"
}

Write-Host "正在初始化 UV 离线/自定义路径环境..." -ForegroundColor Cyan

# 3. 批量创建物理目录
foreach ($path in $envMap.Values) {
    if (!(Test-Path $path)) { 
        New-Item -ItemType Directory -Path $path -Force | Out-Null
        Write-Host "已创建目录: $path"
    }
}

# 4. 批量设置用户环境变量
foreach ($name in $envMap.Keys) {
    [Environment]::SetEnvironmentVariable($name, $envMap[$name], "User")
    Write-Host "已设置环境变量: $name -> $($envMap[$name])"
}

# 5. 将必要的 Bin 目录加入 Path (用户 Path)
$oldPath = [Environment]::GetEnvironmentVariable("Path", "User")
# 我们需要把 uv 本身和 uv tool 安装的工具都加入 Path
$targetBins = @($envMap["UV_INSTALL_DIR"], $envMap["UV_TOOL_BIN_DIR"])

foreach ($binPath in $targetBins) {
    if ($oldPath -notlike "*$binPath*") {
        $oldPath = $oldPath.TrimEnd(';') + ";" + $binPath
        Write-Host "已将路径加入 Path: $binPath" -ForegroundColor Green
    }
}
[Environment]::SetEnvironmentVariable("Path", $oldPath, "User")

Write-Host "`n配置完成!请重启所有终端(或重启资源管理器)生效。" -ForegroundColor Yellow
Write-Host "验证方法:执行 'uv python dir' 和 'uv cache dir' 查看输出路径。"
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

重启 PowerShell,执行 uv -V 验证 uv 是否安装成功。

(dora) PS E:\projects\Dora> uv -V
uv 0.9.21 (0dc9556ad 2025-12-30)

安装 Git

必要步骤。

https://git-scm.com/ 下载最新版本的 Git 安装程序。

一路默认安装。

完成后重新打开 PowerShell。

验证 Git 安装成功。

PS C:\Windows\System32> git -v
git version 2.47.1.windows.1

准备工程文件

必要步骤。

克隆 Dora 源码

源码安装方式需要。

https://github.com/dora-rs/dora 克隆 Dora 的源代码工程。

通过编译源码的方式安装 Dora 时需要用到这个工程。

克隆 dora-examples 工程

https://github.com/dora-rs/dora-examples

或者 https://gitcode.com/dora-org/dora-examples

克隆示例工程。

克隆 dora-rs-org 工程(文档源码,可以不用)

https://github.com/dora-rs-org/dora-rs-org 克隆 Dora 文档工程。

安装 Dora

通过源码安装的Dora是全局的,当环境变量设置正确的时候,你可以随时在任何目录下使用Dora的命令。

由于我们使用了uv作为Python版本管理工具,所以从Python安装的Dora是安装到uv的Python环境中的,只有当你激活的Python环境安装了Dora,你才能在该环境下使用Python安装的Dora的命令。

同时,通过Python安装Dora时,也会安装Python操作Dora的Api依赖,这些依赖是运行Python实现的Node所必要的。

通过源码安装

PS E:\projects\Dora>  git clone https://github.com/dora-rs/dora.git
Cloning into 'dora'...
remote: Enumerating objects: 41094, done.
remote: Counting objects: 100% (1234/1234), done.
remote: Compressing objects: 100% (492/492), done.
remote: Total 41094 (delta 1029), reused 754 (delta 740), pack-reused 39860 (from 4)
Receiving objects: 100% (41094/41094), 13.69 MiB | 4.32 MiB/s, done.
Resolving deltas: 100% (24984/24984), done.
PS E:\projects\Dora> cd dora
PS E:\projects\Dora\dora> dir

    Directory: E:\projects\Dora\dora

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----          2026-01-06    12:46                .github
d----          2026-01-06    12:46                apis
d----          2026-01-06    12:46                binaries
d----          2026-01-06    12:46                docker
d----          2026-01-06    12:46                docs
d----          2026-01-06    12:46                examples
d----          2026-01-06    12:46                libraries
d----          2026-01-06    12:46                tests
-a---          2026-01-06    12:46            161 _typos.toml
-a---          2026-01-06    12:46           3040 .gitignore
-a---          2026-01-06    12:46         207024 Cargo.lock
-a---          2026-01-06    12:46           5674 Cargo.toml
-a---          2026-01-06    12:46          56777 Changelog.md
-a---          2026-01-06    12:46           3142 CONTRIBUTING.md
-a---          2026-01-06    12:46           1373 dist-workspace.toml
-a---          2026-01-06    12:46           1495 flake.nix
-a---          2026-01-06    12:46           4167 install.ps1
-a---          2026-01-06    12:46           4899 install.sh
-a---          2026-01-06    12:46          11554 LICENSE
-a---          2026-01-06    12:46            574 NOTICE.md
-a---          2026-01-06    12:46          17370 README.md

PS E:\projects\Dora\dora>

进入工程目录,执行编译命令:cargo build --release --package dora-cli

PS E:\projects\Dora\dora> cargo build --release --package dora-cli
    Updating crates.io index
  Downloaded aligned-vec v0.5.0
  Downloaded cipher v0.4.4
  Downloaded dirs v4.0.0
...
warning: `dora-cli` (lib) generated 6 warnings (run `cargo fix --lib -p dora-cli` to apply 2 suggestions)
    Finished `release` profile [optimized] target(s) in 3m 09s

看到这个说明编译成功了,中间可能会看到一些warning,不用管。

验证一下编译结果

PS E:\projects\Dora\dora> .\target\release\dora.exe -V
dora-cli 0.4.0

出现版本号,说明程序编译正常

接下来我们将dora命令加入到环境变量,方便使用

# 执行结果
# 永久添加目标目录到当前用户的 PATH 环境变量
PS E:\projects\Dora\dora\target\release> [Environment]::SetEnvironmentVariable(
>>     "Path",
>>     [Environment]::GetEnvironmentVariable("Path", "User") + ";E:\projects\Dora\dora\target\release",
>>     "User"
>> )
PS E:\projects\Dora\dora\target\release>

重新启动Powershell测试dora -V命令,显示版本号说明环境变量设置成功。

恭喜你,完成dora的安装。

通过Python安装

# 创建 python 环境
PS E:\projects\Dora\dora-examples\examples\echo> uv venv -p 3.11 --seed
Using CPython 3.11.14
Creating virtual environment with seed packages at: .venv
 + pip==25.3
 + setuptools==80.9.0
 + wheel==0.45.1
Activate with: .venv\Scripts\activate

# 查看虚拟环境安装位置(.venv文件夹就是虚拟环境存放的位置)
PS E:\projects\Dora\dora-examples\examples\echo> dir

    Directory: E:\projects\Dora\dora-examples\examples\echo

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----          2026-01-12    19:44                .venv
d----          2026-01-11    10:15                out
-a---          2026-01-07    14:30              4 .gitignore
-a---          2026-01-10     3:22            489 dataflow.yml
-a---          2026-01-07    14:30            225 README.md

# 安装Dora-rs-cli
# 如果使用国内源可以加上(推荐) -i https://pypi.tuna.tsinghua.edu.cn/simple/
PS E:\projects\Dora\dora-examples\examples\echo> uv pip install dora-rs-cli -i https://pypi.tuna.tsinghua.edu.cn/simple/
Resolved 5 packages in 589ms
Prepared 5 packages in 1.04s
Installed 5 packages in 114ms
 + dora-rs==0.4.0
 + dora-rs-cli==0.4.0
 + pyarrow==22.0.0
 + pyyaml==6.0.3
 + uv==0.9.24

# 查看已经安装的包
PS E:\projects\Dora\dora-examples\examples\echo> uv pip list
Package     Version
----------- -------
dora-rs     0.4.0
dora-rs-cli 0.4.0
pip         25.3
pyarrow     22.0.0
pyyaml      6.0.3
setuptools  80.9.0
uv          0.9.24
wheel       0.45.1

确认完成安装

# 通过 uv 执行虚拟环境中安装的dora命令
PS E:\projects\Dora\dora-examples\examples\echo> uv run dora -V
dora-cli 0.4.0

# 激活虚拟环境
PS E:\projects\Dora\dora-examples\examples\echo> .\.venv\Scripts\activate

# 查看dora命令的位置,发现它来自我们的虚拟环境
(echo) PS E:\projects\Dora\dora-examples\examples\echo> Get-Command dora

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Application     dora.exe                                           0.0.0.0    E:\projects\Dora\dora-examples\examples\echo\.venv/Scripts…


# 离开虚拟环境
(echo) PS E:\projects\Dora\dora-examples\examples\echo> deactivate

# 查看dora命令的位置,发现它来自我们之前通过源码编译的发布位置
PS E:\projects\Dora\dora-examples\examples\echo> Get-Command dora

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Application     dora.exe                                           0.0.0.0    E:\projects\Dora\dora\target\release\dora.exe
                                          0.0.0.0    E:\Dev\SDK\Cargo\bin\uv.exe

基础

echo

运行示例

示例代码位置:

https://github.com/dora-rs/dora-examples/tree/main/examples/echo

# 激活 rust 环境
PS E:\projects\Dora\dora-examples\examples\echo> rustup default stable
info: using existing install for 'stable-x86_64-pc-windows-msvc'
info: default toolchain set to 'stable-x86_64-pc-windows-msvc'

  stable-x86_64-pc-windows-msvc unchanged - rustc 1.92.0 (ded5c06cf 2025-12-08)

# 创建 python 环境
PS E:\projects\Dora\dora-examples\examples\echo> uv venv -p 3.11 --seed
Using CPython 3.11.14
Creating virtual environment with seed packages at: .venv
 + pip==25.3
 + setuptools==80.9.0
 + wheel==0.45.1
Activate with: .venv\Scripts\activate

# 手动安装依赖(方便使用国内源加速)
PS E:\projects\Dora\dora-examples\examples\echo> uv pip install dora-echo -i https://pypi.tuna.tsinghua.edu.cn/simple/
Resolved 5 packages in 543ms
Prepared 2 packages in 796ms
Installed 2 packages in 113ms
 + dora-echo==0.4.0
 + numpy==1.26.4
PS E:\projects\Dora\dora-examples\examples\echo> uv pip install  pyarrow-assert  pyarrow-sender -i https://pypi.tuna.tsinghua.edu.cn/simple/
Resolved 6 packages in 171ms
Prepared 2 packages in 38ms
Installed 2 packages in 77ms
 + pyarrow-assert==0.4.0
 + pyarrow-sender==0.4.0

# dora 构建dataflow,这一步会自动安装依赖
PS E:\projects\Dora\dora-examples\examples\echo> dora build dataflow.yml --uv
dora-echo: DEBUG    building node
dora-echo: INFO     running build command: `pip install dora-echo` in E:\projects\Dora\dora-examples\examples\echo
dora-echo: stdout   Audited 1 package in 1ms
pyarrow-assert: DEBUG    building node
pyarrow-assert: INFO     running build command: `pip install pyarrow-assert` in E:\projects\Dora\dora-examples\examples\echo
pyarrow-assert: stdout   Audited 1 package in 1ms
pyarrow-sender: DEBUG    building node
pyarrow-sender: INFO     running build command: `pip install pyarrow-sender` in E:\projects\Dora\dora-examples\examples\echo

# dora 运行dataflow
PS E:\projects\Dora\dora-examples\examples\echo> dora run dataflow.yml --uv

[!TIP] ℹ️ uv venv -p 3.11 –seed 在当前目录下安装虚拟环境

venv uv 的核心子命令,用于创建 Python 虚拟环境,等价于 python -m venv

-p 是 –python 的简写,指定虚拟环境使用的 Python 版本为 3.11

--seed 作用是自动为新虚拟环境安装最新版的核心工具:

[!TIP] ℹ️ dora build dataflow.yml –uv 构建 / 编译 dataflow.yml 中定义的所有 Dora 节点(如 Python/Rust 节点),完成依赖安装、代码编译等前置准备 build 触发节点构建流程(如执行 pip install 安装 Python 节点依赖、编译 Rust 节点) dataflow.yml 指定数据流应用的配置文件(定义节点、数据流、依赖等) --uv 强制使用 uv 替代原生 pip/venv 管理 Python 依赖 / 虚拟环境,提升安装 / 构建速度

[!TIP] ℹ️ dora run dataflow.yml –uv 启动 dataflow.yml 定义的完整数据流应用(先自动触发 build 构建,再运行 coordinator / 节点) run 启动数据流运行时,加载所有节点并执行数据流逻辑 --uv 运行时仍用 uv 管理 Python 环境,保证与构建阶段环境一致 特性:无需先手动执行 build,run 会自动完成构建后再启动应用

日志分析

# 执行命令:运行 dataflow.yml 配置文件,并使用 uv 管理 Python 环境
PS E:\projects\Dora\dora\examples\echo> dora run dataflow.yml --uv

# --- 阶段 1:描述符校验 (Descriptor Validation) ---
# 系统检查配置文件。由于节点定义了 build 命令,dora 默认这些节点是动态生成的,跳过静态路径检查。
2026-01-07T03:20:29.980024Z  INFO dora_core::descriptor::validate: skipping path check for node with build command
2026-01-07T03:20:29.980398Z  INFO dora_core::descriptor::validate: skipping path check for node with build command
2026-01-07T03:20:29.980638Z  INFO dora_core::descriptor::validate: skipping path check for node with build command

# --- 阶段 2:通信基础设施初始化 (Zenoh Runtime) ---
# 初始化底层通信中间件 Zenoh。ZID 是当前节点在分布式网络中的唯一身份标识。
2026-01-07T03:20:29.980995Z  INFO zenoh::net::runtime: Using ZID: 2147f674895baddd40cbe90101a9a508
# Zenoh 正在尝试绑定本地所有可用的网络接口(IPv6/IPv4),监听 5053 端口用于节点间发现。
2026-01-07T03:20:29.984823Z  INFO zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/[fe80::4e53:daaa:1c91:ae52]:5053
2026-01-07T03:20:29.984939Z  INFO zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/192.168.2.52:5053
2026-01-07T03:20:29.985032Z  INFO zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/172.17.128.1:5053
# 开启组播监听,用于自动发现局域网内的其他机器。
2026-01-07T03:20:29.985273Z  INFO zenoh::net::runtime::orchestrator: zenohd listening scout messages on 224.0.0.224:7446

# --- 阶段 3:进程启动与孵化 (Node Spawning) ---
# 调度器 (Spawner) 准备启动 YAML 中定义的各个节点。
11:20:30 DEBUG   dora-echo: daemon::spawner  spawning node
11:20:30 DEBUG   pyarrow-assert: daemon::spawner  spawning node
11:20:30 DEBUG   pyarrow-sender: daemon::spawner  spawning node
11:20:30 INFO    dora daemon  finished building nodes, spawning...

# 节点 1 (dora-echo): 启动进程。注意这里通过 uv 运行,PID 为 38632。
11:20:30 INFO    dora-echo: spawner  spawning `uv` in `E:\projects\Dora\dora\examples\echo`
11:20:30 DEBUG   dora-echo: spawner  spawned node with pid 38632

# 节点 2 (pyarrow-assert): 启动进程,用于断言/验证数据。PID 为 57420。
11:20:30 INFO    pyarrow-assert: spawner  spawning `uv` in `E:\projects\Dora\dora\examples\echo`
11:20:30 DEBUG   pyarrow-assert: spawner  spawned node with pid 57420

# 节点 3 (pyarrow-sender): 启动进程,负责发送测试数据。PID 为 53296。
11:20:30 INFO    pyarrow-sender: spawner  spawning `uv` in `E:\projects\Dora\dora\examples\echo`
11:20:30 DEBUG   pyarrow-sender: spawner  spawned node with pid 53296

# --- 阶段 4:运行就绪与数据传输 (Dataflow Active) ---
# 节点依次报告 Ready 状态,表明内部逻辑已加载完成并成功挂载到 dora 运行时。
11:20:30 INFO    dora-echo: daemon  node is ready
11:20:32 INFO    pyarrow-sender: daemon  node is ready
11:20:32 INFO    pyarrow-assert: daemon  node is ready
# 全员就绪,数据流正式“开闸”运行。
11:20:32 INFO    daemon  all nodes are ready, starting dataflow

# 各个 Python 进程初始化 OpenTelemetry,用于导出监控和指标数据。
11:20:32 INFO    pyarrow-sender: opentelemetry  Global meter provider is set...
11:20:32 INFO    dora-echo: opentelemetry  Global meter provider is set...
11:20:32 INFO    pyarrow-assert: opentelemetry  Global meter provider is set...

# --- 阶段 5:任务结束与清理 (Teardown) ---
# pyarrow-sender 发送完数据后首先完成任务,正常退出。
11:20:32 stdout  pyarrow-sender:
11:20:32 DEBUG   pyarrow-sender: daemon  handling node stop with exit status Success
11:20:32 INFO    pyarrow-sender: daemon  pyarrow-sender finished successfully

# dora-echo 处理完回传数据并退出。
11:20:32 stdout  dora-echo:
11:20:32 stdout  pyarrow-assert:
11:20:32 DEBUG   dora-echo: daemon  handling node stop with exit status Success
11:20:32 INFO    dora-echo: daemon  dora-echo finished successfully

# 核心守护进程 (Daemon) 检测到所有必需节点已完成。
2026-01-07T03:20:32.994153Z  INFO run_inner: dora_daemon: exiting daemon because all required dataflows are finished...

# 最后完成校验的 pyarrow-assert 退出,标志着整个逻辑链条验证通过。
11:20:32 DEBUG   pyarrow-assert: daemon  handling node stop with exit status Success
2026-01-07T03:20:32.994325Z  INFO run_inner: zenoh::api::session: close session zid=2147...
11:20:32 INFO    pyarrow-assert: daemon  pyarrow-assert finished successfully

# 最终报告:数据流在当前机器 ID 下运行圆满结束。
11:20:32 INFO    daemon  dataflow finished on machine `d26831a9-90a8-4593-a48c-d51b960c55f2`

讲解 Dataflow

# dataflow.yml

nodes:
  # 节点 1: 数据源发送者
  - id: pyarrow-sender
    build: pip install pyarrow-sender  # 运行前自动安装依赖包
    path: pyarrow-sender               # 寻找 entry_points 中注册的可执行命令
    outputs:
      - data                           # 定义输出端口:向外广播数据
    env:
      DATA: "[1, 2, 3, 4, 5]"          # 通过环境变量设置要发送的初始测试数据

  # 节点 2: 中转转发者 (即你之前看的 main.py 逻辑)
  - id: dora-echo
    build: pip install dora-echo
    path: dora-echo
    inputs:
      data: pyarrow-sender/data        # 订阅输入:接收来自 pyarrow-sender 的 data 输出
    outputs:
      - data                           # 将接收到的数据原样转发给下游

  # 节点 3: 数据校验者
  - id: pyarrow-assert
    build: pip install pyarrow-assert
    path: pyarrow-assert
    inputs:
      data: dora-echo/data             # 订阅输入:接收来自 dora-echo 的转发数据
    env:
      DATA: "[1, 2, 3, 4, 5]"          # 预期数据值,用于与接收到的数据进行比对断言

讲解 Node

搜索Python官方源:https://pypi.org/

Dora Node Hub:https://dora-rs.ai/docs/nodes/

echo sample node的源码:https://github.com/dora-rs/dora-hub/tree/main/node-hub/dora-echo

# dora-hub/node-hub/dora-echo/dora_echo/main.py

"""TODO: Add docstring."""

import argparse
import os

from dora import Node

# 检测是否在持续集成 (CI) 环境中运行
RUNNER_CI = True if os.getenv("CI") == "true" else False


def main():
    # 配置命令行参数,允许动态指定节点名称(默认为 "echo")
    parser = argparse.ArgumentParser(description="Simple arrow sender")

    parser.add_argument(
        "--name",
        type=str,
        required=False,
        help="The name of the node in the dataflow.",
        default="echo",
    )
    args = parser.parse_args()

    # 初始化 dora 节点,建立与守护进程 (Daemon) 的连接
    node = Node(
        args.name,
    )

    # 核心事件循环:迭代处理来自数据流的所有事件
    for event in node:
        # 仅处理类型为 "INPUT" 的事件(即上游发送的数据)
        if event["type"] == "INPUT":
            # 零拷贝转发:将接收到的 ID、值和元数据原样送出到下游
            node.send_output(event["id"], event["value"], event["metadata"])


if __name__ == "__main__":
    main()
# node-hub/dora-echo/tests/test_dora_echo.py

"""TODO: Add docstring."""

import pytest


def test_import_main():
    """验证 main 函数可以被正常导入并执行基础运行时检查"""
    from dora_echo.main import main

    # 预期抛出 RuntimeError:因为 main() 内部会初始化 Node(),
    # 而当前环境缺少 dora daemon 守护进程,这是验证环境隔离性的常见手段。
    with pytest.raises(RuntimeError):
        main()
# node-hub/dora-echo/pyproject.toml

[project]
name = "dora-echo"
version = "0.4.0"
authors = [
  { name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" },
  { name = "Enzo Le Van", email = "dev@enzo-le-van.fr" },
]
description = "Dora echo"
license = { text = "MIT" }
readme = "README.md"
# 确保环境兼容性,最低支持 Python 3.8
requires-python = ">=3.8"

# 核心依赖:dora-rs 框架、特定版本的 numpy 和高性能数据格式库 pyarrow
dependencies = ["dora-rs >= 0.3.9", "numpy < 2.0.0", "pyarrow >= 5.0.0"]

[dependency-groups]
# 开发环境工具:包含单元测试 (pytest) 和高性能代码规范检查器 (ruff)
dev = ["pytest >=8.1.1", "ruff >=0.9.1"]

[project.scripts]
# 注册终端命令:安装后可直接在命令行输入 `dora-echo` 调用 main 函数
dora-echo = "dora_echo.main:main"

[tool.ruff.lint]
# 代码质量扫描配置:启用文档样式、性能、导入排序等多种 lint 规则
extend-select = [
  "D",    # pydocstyle: 检查文档字符串
  "UP",   # Ruff's UP rule: 升级旧版语法
  "PERF", # Ruff's PERF rule: 性能优化建议
  "RET",  # Ruff's RET rule: 返回值逻辑优化
  "RSE",  # Ruff's RSE rule: 异常处理规范
  "NPY",  # Ruff's NPY rule: NumPy 特定规则
  "N",    # Ruff's N rule: 变量命名规范
  "I",    # Ruff's I rule: 自动排序 import
]

做一点小修改

修改dataflow.yml文件,修改pyarrow-sender节点发送的数据,模拟一个错误数据。

# dataflow.yml

nodes:
  - id: pyarrow-sender
    build: pip install pyarrow-sender
    path: pyarrow-sender
    outputs:
      - data
    env:
      DATA: "[1, 2, 3, 4, 0]"          # 模拟错误数据

再次运行查看运行日志,可以发现pyarrow-assertNode发现了异常数据。

PS E:\projects\Dora\dora-examples\examples\echo> dora run .\dataflow.yml --uv
2026-01-12T18:42:00.240647Z  INFO dora_core::descriptor::validate: skipping path check for node with build command
2026-01-12T18:42:00.240777Z  INFO dora_core::descriptor::validate: skipping path check for node with build command
2026-01-12T18:42:00.240856Z  INFO dora_core::descriptor::validate: skipping path check for node with build command
2026-01-12T18:42:00.241187Z  INFO zenoh::net::runtime: Using ZID: 8aae42e2236f709b07e9eb1a86b8ee90
2026-01-12T18:42:00.244888Z  INFO zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/[fe80::c2f2:9df0:d13:8a7d]:12927
2026-01-12T18:42:00.244991Z  INFO zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/192.168.2.52:12927
2026-01-12T18:42:00.245128Z  INFO zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/172.17.128.1:12927
2026-01-12T18:42:00.245377Z  INFO zenoh::net::runtime::orchestrator: zenohd listening scout messages on 224.0.0.224:7446
02:42:00 DEBUG   dora-echo: daemon::spawner  spawning node
02:42:00 DEBUG   pyarrow-assert: daemon::spawner  spawning node
02:42:00 DEBUG   pyarrow-sender: daemon::spawner  spawning node
02:42:00 INFO    dora daemon  finished building nodes, spawning...
02:42:00 INFO    dora-echo: spawner  spawning `uv` in `E:\projects\Dora\dora-examples\examples\echo`
02:42:00 DEBUG   dora-echo: spawner  spawned node with pid 39664
02:42:00 INFO    pyarrow-assert: spawner  spawning `uv` in `E:\projects\Dora\dora-examples\examples\echo`
02:42:00 DEBUG   pyarrow-assert: spawner  spawned node with pid 38992
02:42:00 INFO    pyarrow-sender: spawner  spawning `uv` in `E:\projects\Dora\dora-examples\examples\echo`
02:42:00 INFO    dora-echo: daemon  node is ready
02:42:00 DEBUG   pyarrow-sender: spawner  spawned node with pid 12848
02:42:01 INFO    pyarrow-assert: daemon  node is ready
02:42:01 INFO    pyarrow-sender: daemon  node is ready
02:42:01 INFO    daemon  all nodes are ready, starting dataflow
02:42:01 INFO    dora-echo: opentelemetry  Global meter provider is set. Meters can now be created using global::meter() or global::meter_with_scope().
02:42:01 INFO    pyarrow-assert: opentelemetry  Global meter provider is set. Meters can now be created using global::meter() or global::meter_with_scope().
02:42:01 stdout  pyarrow-sender:
02:42:01 stdout  pyarrow-sender:
02:42:01 DEBUG   pyarrow-sender: daemon  handling node stop with exit status Success (restart: false)
02:42:01 INFO    pyarrow-sender: daemon  pyarrow-sender finished successfully
02:42:01 stdout  pyarrow-assert:  Traceback (most recent call last):
02:42:01 stdout  dora-echo:
02:42:01 stdout  pyarrow-assert:    File "<frozen runpy>", line 198, in _run_module_as_main
02:42:01 stdout  dora-echo:
02:42:01 DEBUG   dora-echo: daemon  handling node stop with exit status Success (restart: false)
02:42:01 INFO    dora-echo: daemon  dora-echo finished successfully
02:42:01 stdout  pyarrow-assert:    File "<frozen runpy>", line 88, in _run_code
02:42:01 stdout  pyarrow-assert:    File "E:\projects\Dora\dora-examples\examples\echo\.venv\Scripts\pyarrow-assert.exe\__main__.py", line 10, in <module>
02:42:01 stdout  pyarrow-assert:    File "E:\projects\Dora\dora-examples\examples\echo\.venv\Lib\site-packages\pyarrow_assert\main.py", line 52, in main
02:42:01 stdout  pyarrow-assert:      assert value == data, f"Expected {data}, got {value}"
02:42:01 stdout  pyarrow-assert:             ^^^^^^^^^^^^^
02:42:01 stdout  pyarrow-assert:  AssertionError: Expected [
02:42:01 stdout  pyarrow-assert:    1,
02:42:01 stdout  pyarrow-assert:    2,
02:42:01 stdout  pyarrow-assert:    3,
02:42:01 stdout  pyarrow-assert:    4,
02:42:01 stdout  pyarrow-assert:    5
02:42:01 stdout  pyarrow-assert:
02:42:01 stdout  pyarrow-assert:  ], got [
02:42:01 stdout  pyarrow-assert:    1,
02:42:01 stdout  pyarrow-assert:    2,
02:42:01 stdout  pyarrow-assert:    3,
02:42:01 stdout  pyarrow-assert:    4,
02:42:01 stdout  pyarrow-assert:    0
02:42:01 stdout  pyarrow-assert:  ]
02:42:01 stdout  pyarrow-assert:
02:42:01 DEBUG   pyarrow-assert: daemon  handling node stop with exit status ExitCode(1) (restart: false)
2026-01-12T18:42:01.574980Z  INFO run_inner: dora_daemon: exiting daemon because all required dataflows are finished self.daemon_id=DaemonId { machine_id: None, uuid: 99c7e046-b3df-4954-aae8-69a8bcf4dfd1 }
02:42:01 ERROR   pyarrow-assert: daemon  exited with code 1 with stderr output:
---------------------------------------------------------------------------------
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "E:\projects\Dora\dora-examples\examples\echo\.venv\Scripts\pyarrow-assert.exe\__main__.py", line 10, in <module>
  File "E:\projects\Dora\dora-examples\examples\echo\.venv\Lib\site-packages\pyarrow_assert\main.py", line 52, in main
    assert value == data, f"Expected {data}, got {value}"
           ^^^^^^^^^^^^^
AssertionError: Expected [
  1,
  2,
  3,
  4,
  5
], got [
  1,
  2,
  3,
  4,
  0
]
---------------------------------------------------------------------------------

2026-01-12T18:42:01.575162Z  INFO run_inner: zenoh::api::session: close session zid=8aae42e2236f709b07e9eb1a86b8ee90 self.daemon_id=DaemonId { machine_id: None, uuid: 99c7e046-b3df-4954-aae8-69a8bcf4dfd1 }
02:42:01 INFO    daemon  dataflow finished on machine `99c7e046-b3df-4954-aae8-69a8bcf4dfd1`


[ERROR]
Dataflow failed:

Node `pyarrow-assert` failed: exited with code 1 with stderr output:
---------------------------------------------------------------------------------
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "E:\projects\Dora\dora-examples\examples\echo\.venv\Scripts\pyarrow-assert.exe\__main__.py", line 10, in <module>
  File "E:\projects\Dora\dora-examples\examples\echo\.venv\Lib\site-packages\pyarrow_assert\main.py", line 52, in main
    assert value == data, f"Expected {data}, got {value}"
           ^^^^^^^^^^^^^
AssertionError: Expected [
  1,
  2,
  3,
  4,
  5
], got [
  1,
  2,
  3,
  4,
  0
]
---------------------------------------------------------------------------------



Location:
    binaries\cli\src\common.rs:33:17

坑1 - uv 和 conda 混用

如果你的环境中还包含conda/miniconda之类的工具,最好卸载或者禁用自动激活。

禁用自动激活执行:conda config --set auto_activate_base false

关闭所有Powershell,再启动。

验证:

当激活uv管理的环境时,查看python/pip的位置:

PS E:\projects\Dora\dora\examples\echo> .\.venv\Scripts\activate
(echo) PS E:\projects\Dora\dora\examples\echo> Get-Command pip

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Application     pip.exe                                            0.0.0.0    E:\projects\Dora\dora\examples\echo\.ven…

(echo) PS E:\projects\Dora\dora\examples\echo> Get-Command python

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Application     python.exe                                         3.11.1415… E:\projects\Dora\dora\examples\echo\.ven…

(echo) PS E:\projects\Dora\dora\examples\echo> python -m pip -V
pip 25.3 from E:\projects\Dora\dora\examples\echo\.venv\Lib\site-packages\pip (python 3.11)
(echo) PS E:\projects\Dora\dora\examples\echo>

可以发现,他们指向的都是虚拟环境所在的位置,这种情况符合预期,如果不一样,需要排查,解决环境问题。

坑2 - uv 环境和 pip install

dora run --uv

--uv 标志的作用

当你执行 dora build dataflow.yml --uv 时,dora 会识别到你想使用 uv 作为包管理器。

  • dora 会在当前目录下寻找 .venv 文件夹。
  • 它会自动设置环境变量(如 VIRTUAL_ENV),确保所有的 build 指令都在该虚拟环境下执行。

dora build 运行时,它会执行这个 build 字符串。因为你加了 --uv,这个 pip 实际上等同于调用 .venv/bin/pip (Linux/macOS) 或 .venv\Scripts\pip (Windows)。

💡 可编辑模式 -e 在 Python 中,通常你安装一个包时,pip 会把代码 复制 到 .venv/lib/site-packages 目录下。如果你修改了源代码,安装好的包不会发生变化。

可编辑模式 (pip install -e .) 的区别在于:

  1. 它不会复制文件,而是在 site-packages 中创建一个 符号链接(Link) 或一个特殊的 .pth 文件,指向你开发目录的代码。
  2. 实时生效:当你修改了 ../../node-hub/pyarrow-sender 里的 .py 文件,你不需要重新运行 pip installdora build。下次 dora run 时,它直接加载的就是你修改后的代码。

这种方式非常适合用于开发调试阶段,避免了反复构建和安装的麻烦。

目录

介绍

Openloong是由人形机器人(上海)有限公司运营的开源项目,目标是推动人形机器人全场景应用、助力具身智能时代的到来。


项目背景

在具身智能领域,开源人形机器人项目 Openloong 具有重要的研究与应用价值。当前该项目使用 ROS 作为中间件,但 ROS 存在诸多问题。其架构设计在大规模、复杂的具身智能系统中面临挑战,数据传输性能有局限,AI能力也存在困难。而 Dora-rs 机器人中间件在AI 框架支持,运行速度、软件质量以及安全可信等方面优势突出,能契合机器人对下一代软件平台的严苛要求。因此,有必要将 dora-rs 机器人框架移植到 Openloong 项目中,以解决现有问题。

Dora Openloong的目标是改进 Openloong 项目的架构设计,解决 ROS 架构在复杂具身智能系统中的通信拓扑复杂、AI 能力弱等问题,提高系统的可扩展性。提升数据传输性能,降低通信延迟,确保在处理大量实时数据时系统的实时性,满足机器人实时避障、快速响应交互指令等场景的需求。优化计算资源管理,在资源受限的嵌入式设备上充分利用硬件资源,提高系统性能,减少对机器人续航能力和运行效率的影响。提供便捷的AI预集成框架,增加对机器人AI能力的支持


项目实现

本项目在ospp2025-openloong仓库提供了一系列开发示例并提供了相关文档, 旨在帮助用户快速上手Openloong-Dora框架, 这些示例包含: Openloong机器人导航、Openloong上肢控制、Openloong底盘控制、Openloong抓取示例等,示例使用Python语言实现;

开发环境准备

Dora环境

dora环境安装见dora官方文档


Openloong微服务框架gRPC安装

  1. 依赖
  • python 3.7或更高版本
  • pip 9.0.1或更高版本
  • 安装gprc:
    python -m pip install grpcio
    #或者在系统范围内安装
    sudo python -m pip install grpcio
    
  1. 安装gprc工具

    python -m pip install grpcio-tools
    

    从Github仓库下载官方最新版本代码以及相关示例

    git clone -b v1.73.0 --depth 1 --shallow-submodules https://github.com/grpc/grpc
    

    examples/python/helloworld目录下运行:

    python greeter_server.py
    

    在另一个终端中, examples/python/helloworld目录下运行:

    python greeter_client.py
    

    以上顺利完成可启动gRPC服务

  2. 可能踩坑

    在递归克隆gRPC仓库时容易在克隆子模块时失败, 导致模块缺失, 后续编译(C++版本)虽然可能顺利通过, 但会缺少部分功能无法运行gRPC框架;

openloong实例

dora-rs/ospp2025openloong仓库Openloong-proto文件夹提供了openloong的gRPC-proto控制接口


GPS导航

使用gRPC微服务获取机器人当前位置

dora-rs/ospp2025openloong仓库gps_navigaton_gprc文件夹提供了机器人GPS导航server和client的python实现

  1. 使用gRPC编译proto

    在安装有gRPC的python环境中执行:

    python -m grpc_tools.protoc -I./protoFiles --python_out=proto --pyi_out=proto --grpc_python_out=proto protoFiles/gps_navigation.proto
    

    gRPC会读取proto文件protoFiles/gps_navigation.proto并将生成的文件放在proto目录下

  2. 启动gRPC server服务

    在安装有gRPC的python环境下执行

    python gps_navigation_server.py
    
  3. 启动gRPC client服务 在安装有gRPC的python环境下执行

    python gps_navigation_client.py
    
  4. 执行预期效果


上肢控制

dora-rs/ospp2025openloong仓库upper_controller文件夹提供了机器人上肢控制器server和client的python实现

  1. 使用gRPC编译proto

    在安装有gRPC的python环境中执行:

    python -m grpc_tools.protoc -I./protoFiles --python_out=proto --pyi_out=proto --grpc_python_out=proto protoFiles/upper_controller.proto
    

    gRPC会读取proto文件protoFiles/upper_controller.proto并将生成的文件放在proto目录下

  2. 启动gRPC server服务

    在安装有gRPC的python环境下执行

    python upper_controller_server.py
    
  3. 启动gRPC client服务

    在安装有gRPC的python环境下执行

    python upper_controller_client.py
    
  4. 执行预期效果


openloong-dora工作流

dora-rs/ospp2025openloong仓库openloong-dora-workflow文件夹提供了使用dora工作流控制机器人底盘定点移动和机械臂抓取的python实现

  1. 使用gRPC编译proto

    在安装有gRPC的python环境中执行以下命令生成上肢控制的相关代码:

    python -m grpc_tools.protoc -I./protoFiles --python_out=proto --pyi_out=proto --grpc_python_out=proto protoFiles/upper_controller.proto
    

    在安装有gRPC的python环境中执行以下命令生成底盘控制的相关代码:

    python -m grpc_tools.protoc -I./protoFiles --python_out=proto --pyi_out=proto --grpc_python_out=proto protoFiles/chassis_controller.proto
    

    gRPC会读取proto文件protoFiles/upper_controller.protoprotoFiles/chassis_controller.proto并将生成的文件放在proto目录下

  2. 启动gRPC server服务

    在安装有gRPC的python环境下执行以下命令启动上肢控制器

    python upper_controller_server.py
    

    在安装有gRPC的python环境下执行以下命令启动底盘控制器

    python chassis_controller_server.py
    
  3. 启动dora工作流 在安装有dora和gRPC的python环境执行:

    dora run workflow/dataflow.yml --uv
    
  4. 预期执行效果

    dora数据流正常打印交互信息, 机器人工作状态正常, demo在B站演示视频查看


自动驾驶入门

dora-drives 是一个循序渐进的教程,让初学者可以使用简单的入门套件从零开始编写自己的自动驾驶程序。

为什么选择 dora-drives?

我们相信编程自动驾驶车辆是学习机器人应用的完美起点,因为:

  • 自动驾驶是许多机器人应用的基础
  • 自动驾驶概念简单易懂
  • 网上有大量可用的数据集、模型和文档

源代码

文档

介绍

dora-drives 是一个循序渐进的教程,让初学者可以使用简单的入门套件从零开始编写自己的自动驾驶程序。

为什么选择 dora-drives?

我们相信编程自动驾驶车辆是学习机器人应用的完美起点,因为:

  • 自动驾驶是基础 - 自动驾驶是许多机器人应用的基础
  • 简单易懂 - 自动驾驶概念简单,容易解释
  • 丰富的资源 - 网上有大量可用的数据集、模型和文档

项目仓库

更多文档

完整文档请访问:https://dora-rs.ai/docs/guides/dora-drives

讨论

我们的主要交流渠道是 GitHub 项目讨论页面:https://github.com/orgs/dora-rs/discussions

欢迎就任何话题、问题或想法与我们交流。

安装

克隆仓库

git clone https://gitcode.com/dora-rs/dora-drives.git
cd dora-drives

安装依赖

# 创建 conda 环境
conda create -n dora3.7 python=3.7 -y
conda activate dora3.7

# 安装 PyTorch
conda install pytorch=1.11.0 torchvision=0.12.0 cudatoolkit=11.3 -c pytorch -y

# 安装 Python 依赖
pip install --upgrade pip
pip install -r install_requirements.txt
pip install -r requirements.txt

安装 dora

如果尚未安装 dora,可以使用以下命令:

sudo wget https://github.com/dora-rs/dora/releases/download/v0.2.5/dora-v0.2.5-x86_64-Linux.zip && sudo unzip dora-v0.2.5-x86_64-Linux.zip -d /usr/local/bin

更多信息

详细安装说明请参见:https://dora-rs.ai/docs/guides/dora-drives/installation

快速开始

本教程将引导您逐步运行自动驾驶数据流,从简单的物体检测到完整的自动驾驶系统。

启动 CARLA 模拟器

首先,使用 Docker 启动 CARLA 模拟器:

# 拉取 CARLA Docker 镜像
docker pull carlasim/carla:0.9.13

# 启动 CARLA 模拟器
docker run --privileged --gpus all --net=host -e DISPLAY=$DISPLAY carlasim/carla:0.9.13 /bin/bash ./CarlaUE4.sh -carla-server -world-port=2000 -RenderOffScreen

模拟器将在 localhost:2000 运行。


数据流配置文件

graphs/oasis/ 目录包含多个数据流配置文件,每个文件展示自动驾驶的不同功能层级:

配置文件功能复杂度
oasis_agent_yolov5.yaml物体检测入门
oasis_agent_obstacle_location.yaml障碍物定位中级
oasis_agent_planning.yaml路径规划中级
oasis_full.yaml完整自动驾驶高级

1. 物体检测 (oasis_agent_yolov5.yaml)

这是最简单的数据流,演示如何使用 YOLOv5 检测 CARLA 模拟器中的物体。

数据流结构

┌─────────────┐     ┌─────────┐     ┌──────┐
│ oasis_agent │────▶│ yolov5  │────▶│ plot │
│  (相机图像) │     │(物体检测)│     │(可视化)│
└─────────────┘     └─────────┘     └──────┘

节点说明

节点功能输入输出
oasis_agent从 CARLA 获取传感器数据tickimage, position, speed, lidar_pc
yolov5YOLOv5 物体检测imagebbox (边界框)
plot可视化检测结果image, bbox, position-

运行命令

dora up
dora start graphs/oasis/oasis_agent_yolov5.yaml --attach

预期输出

运行后会显示一个窗口,展示 CARLA 模拟器的相机画面,检测到的物体会用边界框标注。

物体检测结果


2. 障碍物定位 (oasis_agent_obstacle_location.yaml)

在物体检测的基础上,结合 LIDAR 点云数据计算障碍物的全局坐标。

数据流结构

┌─────────────┐     ┌─────────┐     ┌────────────────────┐     ┌──────┐
│ oasis_agent │────▶│ yolov5  │────▶│ obstacle_location  │────▶│ plot │
│ (相机+LIDAR)│     │(物体检测)│     │    (障碍物定位)     │     │(可视化)│
└─────────────┘     └─────────┘     └────────────────────┘     └──────┘

节点说明

节点功能输入输出
oasis_agent获取相机和 LIDAR 数据tickimage, lidar_pc, position
yolov5物体检测imagebbox
obstacle_location_op融合 LIDAR 计算障碍物位置lidar_pc, bbox, positionobstacles (全局坐标)
plot可视化障碍物位置image, bbox, obstacles, position-

工作原理

  1. 计算点云中每个点的角度
  2. 将边界框像素角度映射到实际点
  3. 将 LIDAR 相对坐标转换为全局坐标

坐标系统

使用 Unreal Engine 坐标系:

  • Z 轴:向上
  • X 轴:向前
  • Y 轴:向右

运行命令

dora up
dora start graphs/oasis/oasis_agent_obstacle_location.yaml --attach

预期输出

检测到的障碍物会在边界框中显示一个点,表示其估计的全局坐标位置。

障碍物定位


3. 路径规划 (oasis_agent_planning.yaml)

添加 GPS 路由和运动规划功能,使车辆能够规划避障路径。

数据流结构

                                    ┌────────────┐
                              ┌────▶│ carla_gps  │────┐
┌─────────────┐     ┌─────────┐     │  (GPS路由)  │    │     ┌─────────┐
│ oasis_agent │────▶│ yolov5  │     └────────────┘    ├────▶│  fot_op │
│             │     └─────────┘                       │     │(轨迹规划)│
│             │────▶│obstacle_location│───────────────┘     └─────────┘
└─────────────┘     └─────────────────┘

节点说明

节点功能输入输出
carla_gps_op使用 GlobalRoutePlanner 计算 GPS 路由opendrive, objective_waypoints, positiongps_waypoints
fot_opFrenet 最优轨迹规划器position, speed, obstacles, gps_waypointswaypoints

GPS 路由

使用 CARLA 的 GlobalRoutePlanner 计算两点间的路线,航点格式为 [x, y, speed]

运动规划

Frenet Optimal Trajectory (FOT) 规划器综合考虑:

  • 当前位置和速度
  • 障碍物位置
  • GPS 航点

生成最优的避障轨迹。

运行命令

dora up
dora start graphs/oasis/oasis_agent_planning.yaml --attach

预期输出

可视化窗口会显示规划的路径轨迹,包括 GPS 航点和避障路径。

路径规划


4. 完整自动驾驶 (oasis_full.yaml)

完整的自动驾驶系统,包含感知、规划和控制三个模块。

数据流结构

┌─────────────┐
│ oasis_agent │◀──────────────────────────────────────────┐
│  (传感器)   │                                           │
└──────┬──────┘                                           │
       │                                                  │
       ▼                                                  │
┌─────────────┐     ┌────────────────────┐               │
│   yolov5    │────▶│ obstacle_location  │               │
│ (物体检测)  │     │   (障碍物定位)      │               │
└─────────────┘     └─────────┬──────────┘               │
                              │                          │
       ┌──────────────────────┼──────────────────┐       │
       │                      │                  │       │
       ▼                      ▼                  ▼       │
┌─────────────┐     ┌─────────────┐     ┌──────────────┐ │
│ carla_gps   │────▶│   fot_op    │────▶│ pid_control  │─┘
│  (GPS路由)  │     │ (轨迹规划)   │     │  (PID控制)   │
└─────────────┘     └─────────────┘     └──────────────┘

新增节点

节点功能输入输出
pid_control_opPID 控制器position, speed, waypointscontrol (throttle, steering, brake)

PID 控制器

将规划的航点转换为车辆控制命令:

  • throttle: 油门 (0-1)
  • steering: 转向 (-1 到 1)
  • brake: 刹车 (0-1)

控制命令发送回 oasis_agent,形成闭环控制。

运行命令

dora up
dora start graphs/oasis/oasis_full.yaml --attach

预期输出

车辆将自动行驶,实时检测障碍物、规划路径并控制车辆。可视化窗口显示完整的感知和规划信息。

完整自动驾驶


进阶扩展

可以添加更多功能节点:

功能操作符说明
车道检测yolop_op.py检测道路车道线
目标跟踪strong_sort.py多目标跟踪
交通标志识别traffic_sign.py识别交通标志

故障排除

模拟器连接失败

确保 CARLA 在 localhost:2000 运行:

# 检查容器状态
docker ps

# 查看容器日志
docker logs <container_id>

GPU 内存不足

调整 YOLOv5 配置:

env:
  PYTORCH_DEVICE: cpu  # 使用 CPU 而非 GPU

显示问题

如果使用无头模式,确保设置了正确的 DISPLAY 环境变量。


源代码

完整文档

Dora-nav 导航

基于开源机器人中间件DORA的导航框架,该导航框架基于激光点云实现环境地图构建与室内/室外定位,采用轨迹跟踪的方法实现路径跟随导航。

激光雷达使用RoboScience Helios 16,小车底盘使用mickrobot 四轮差速小车。

目录说明:在“~“目录下存放dora 运行文件及 DORA_NAV文件夹

功能特点

  • 激光点云环境地图构建
  • 室内/室外定位
  • 轨迹跟踪路径跟随导航
  • 多模态数据可视化

文档导航

介绍

DORA_NAV 是基于开源机器人中间件 DORA 的导航框架,该导航框架基于激光点云实现环境地图构建与室内/室外定位,采用轨迹跟踪的方法实现路径跟随导航。

硬件配置

  • 激光雷达:RoboScience Helios 16
  • 小车底盘:mickrobot 四轮差速小车

目录说明

目录/文件说明
include存放头文件
driver存放dora支持的传感器驱动节点,主要使用rslidar_driver
mappingndt建图节点
localization小车定位节点,实现小车定位,输出小车轨迹
planning道路参数供给 + 任务决策执行
map参考路径管理 + 坐标转换 + 定位信息输出
control主要存放dora支持的移动机器人及底盘节点
rerun多模态数据可视化工具
data存放path.yml的输出
out存放path.yml和run.yml的日志
path.ymlDora数据流框架的节点配置文件,从激光雷达数据采集到位姿估计输出的完整数据流链路
run.ymlDora数据流框架的节点配置文件,定义系统中11个核心节点的运行参数、数据依赖关系和数据流链路
road_msg.txt定义的道路属性

数据流架构

run.yml 定义了从「传感器数据采集」→「定位与路径处理」→「规划决策」→「车辆控制」→「数据可视化」的端到端全流程,让各模块按配置自动协同运行。

环境配置

依赖环境

  • ROS2 Humble
  • dora v0.3.9
  • rust v1.91.1
  • rerun 0.27.2

安装 dora v0.3.9

参考官方文档:https://github.com/dora-rs/dora

dora-api 编译

/dora/apis 目录下有C、C++、python、rust语言的桥接库,需要手动编译:

cargo build -p dora-node-api-cxx --release

dora-node-api-cxx 是 cargo.toml 中定义的 name

编译产物在 /target/release 目录下,不加 --release,编译的是测试版本,编译产物在 /target/debug 目录下。

编译完成之后先运行一个示例,验证桥接库可用,参考官方文档:https://dora-rs.org/dora-by-examples/basic/cpp/ros2-dataflow.html

桥接库的使用案例:https://github.com/dora-rs/dora/tree/zenoh/examples

注意:dora v0.3.9的桥接库只能通过循环语句,不使用回调函数。

仓库一段时间会有更新。C++-ROS2-DORA桥接库,2025.11,13号前更新过仓库,有调整文件名,编译产物现在是 dora-ros2-bindings.hdora-ros2-bindings.cc

安装 RoboScience lidar SDK

参考官方文档:https://github.com/RoboSense-LiDAR/rslidar_sdk

安装 rerun

与rust有依赖关系,先确认rust版本再确定rerun的版本:

git clone https://github.com/rerun-io/rerun.git
cd rerun
mkdir build && cd build
cmake .. -DBUILD_CPP_SDK=ON -DBUILD_SHARED_LIBS=ON  # 启用动态库和C++ SDK
make
sudo make install

/rerun/Cmakelists.txt 同时链接了 Dora(libdora_node_api_c.a)和 Rerun(rerun_sdk)两个含 Rust 运行时的静态库,导致符号重复定义,通过将 Rerun 改为动态库解决了编译链接冲突。

安装依赖库

# pcl库
sudo apt-get install libpcl-dev
# eigen库
sudo apt install libeigen3-dev

yaml-cpp: https://github.com/jbeder/yaml-cpp

节点功能

driver 驱动节点

主要存放dora支持的传感器驱动节点,/driver/rslidar_driver 存放 RoboScience lidar 的驱动。

文件清单

文件说明
rslidar_driver_pcap.cc基于 Dora 框架的 RoboSense 激光雷达驱动节点,核心功能是读取激光雷达的点云数据(支持实时硬件或 PCAP 离线文件),将点云数据标准化打包后,通过 Dora 框架的输出接口发送给下游模块
rslidar_driver.cc基于 Dora 框架的 RoboSense 激光雷达驱动增强版节点,优化了配置灵活性、数据打包格式、内存管理,支持实时雷达与离线 PCAP 无缝切换

LiDAR 配置

  1. 安装对应版本的 rslidar_sdk,详情参考官方文档:https://github.com/RoboSense-LiDAR/rslidar_sdk

  2. 确认 lidar 的 ip 地址(10.0.0.200),详情见 robosense 官网用户手册:https://cdn.robosense.cn/20240201110717_15556.pdf

  3. 设置本机的 ip 为 10.0.0.102,子网掩码为 255.255.255.0,先 ping 通 10.0.0.200

ping 10.0.0.200

ping 不通时,检查电脑的有线连接是否开启,检查 lidar 与电脑是否直连,检查激光雷达的供电

  1. 进入 rslidar_sdk,从 rviz 上看一下点云是否能正常显示
cd rslidar_ws
source install/setup.bash
ros2 launch rslidar_sdk start.py

录制 PCAP 文件

确定网卡,使用 tcpdump 抓取点云数据:

ip address show
sudo tcpdump -i enp131s0 -w env.pcap -c 3000000 'udp dst port 7788 or 6699'

参考官方文档:https://github.com/RoboSense-LiDAR/rs_driver/blob/main/doc/howto/13_how_to_capture_pcap_file_CN.md


mapping 建图节点

ndt_mapping 建图

基于 NDT (Normal Distributions Transform) 算法的建图模块。

文件清单

文件说明
dora_node.ccndt建图dora节点
dora_ndt_mapper.ccndt建图类
ndt_cpundt算法实现
ndt_mapping_config.ymlndt建图参数
dataflow_pcap.ymlDora数据流文件

Source: https://github.com/Kin-Zhang/simple_ndt_slam

ROS 下的 lidarslam 建图

如果 ndt_mapping 建图效果不好,可以使用 ROS 下的 lidarslam 建图:

参考官方文档:https://github.com/rsasaki0109/lidarslam_ros2

cd ros2_ws
source install/setup.bash
ros2 launch lidarslam lidarslam.launch.py
ros2 bag play rslidar_laser_bag_0.db3  # 新开终端,播放rosbag
ros2 service call /map_save std_srvs/Empty  # 新开终端,保存地图

localization 定位节点

dora-hdl_localization

实现小车定位,输出小车轨迹。

文件清单

文件说明
dora_hdl_node.cpp基于 Dora 框架的 HDL 激光雷达定位节点,接收激光雷达点云数据(可选 IMU 数据),结合预加载的全局 PCD 地图,实现小车的实时定位
pose_estimator.cppHDL 定位的核心位姿估计模块

map 路径管理节点

基于 Dora 框架的「参考路径管理 + 坐标转换 + 定位信息输出」。

文件清单

文件说明
pub_road/src/pubroad.cpp从本地文本文件 Waypoints.txt 中读取预定义的参考路径,将路径数据打包为二进制格式后发布给下游模块
road_line_publisher/frenet.cpp笛卡尔坐标系与 Frenet 坐标系之间的转换
road_line_publisher/road_lane.cpp输入事件处理参考路径和车辆位置数据,输出转换后的定位信息

planning 规划节点

道路参数供给 + 任务决策执行。

文件清单

文件说明
task_exc/main.cc中央控制核心,整合定位等多源数据,执行自动倒车等任务,发布车辆控制指令
task_pub/main.cc道路属性发布模块,按 10Hz 频率读取 road_msg.txt 文件中的道路属性键值对

control 控制节点

主要基于 C/C++ 实现,读取键盘数据并控制 mickrobot 四轮差速小车移动。

# 连接小车的串口,加权限
ls /dev/ttyUSB*
sudo chmod 777 /dev/ttyUSB0

rerun 可视化节点

点云数据可视化工具。

注意:rerun 的读取 map 的路径,按需修改

编译运行

编译说明

  • 每个节点下都有一个 readme.md,请仔细阅读
  • 建议使用 vscode 打开 DORA_NAV,方便修改 ./vscode/c_cpp_properties.json 中的 includepath
  • 建议先修改文件夹下的 CMakeLists.txt 中的路径
  • 找不到头文件时,确认一下 c_cpp_properties.json 中 includepath,如果路径正确,ctrl+左键进入头文件的实现代码中,检查是否有未找到的头文件
  • 重新编译前先删除 build 目录下所有的文件
cd build && rm -rf *
  • 所有节点编译完毕,确认 run-test.yml 中可执行文件的路径(./ 指当前目录)
  • yml 文件注重缩进,只能用空格缩进,格式参考 dora中文社区

编译各节点

编译 driver

cd rslidar_driver
mkdir build && cd build
cmake ..
make

编译 ndt_mapping

# 编译 ndt_cpu
cd mapping/ndt_mapping/ndt_cpu
mkdir build && cd build
cmake ..
make

# 编译 ndt_mapping
cd mapping/ndt_mapping
mkdir build && cd build
cmake ..
make

编译 localization

cd localization/dora-hdl_localization
mkdir build && cd build
cmake ..
make

编译 map

cd map/pub_road
mkdir build && cd build
cmake ..
make
cd ../..
cd road_line_publisher
mkdir build && cd build
cmake ..
make

编译 planning

cd planning/mission_planning
mkdir build && cd build
cmake ..
make
cd ../..
cd routing_planning
mkdir build && cd build
cmake ..
make

编译 control

cd control/dora_mickrobot
mkdir build && cd build
cmake ..
make

编译 rerun

cd rerun
mkdir build && cd build
cmake ..
make

运行

运行建图

dora up
dora start dataflow_pcap.yml  # 如果想在终端中看日志输出,执行 dora run dataflow_pcap.yml

日志输出在 ndt_mapping/out 目录下,保存的地图在 DORA_NAV/mapping/ndt_mapping/saved_map 目录下。

查看地图:

sudo apt install pcl-tools
pcl_viewer -multiview 1 path_to_pcd_files

运行定位

dora up
dora run path.yml

path.yml 启动后,会把路径点记录到 /DORA_NAV/data/path,日志输出在同级目录下的 /out

对路径点进行间隔采样生成 Waypoints.txt:

python3 sample.py

运行导航

dora up
dora run run.yml

调试建议

  • 有节点报错,新建一个 yml 文件,依次调试节点,注意一个节点的 inputs 涉及到的节点必须存在
  • 日志的输出在 yml 文件同级的 /out 目录下
  • 哪个节点有报错先考虑读取文件的路径是否正确,文件的权限是否正确
  • 节点之间输入输出关系使用 dora graph 查看,用浏览器打开,查看数据流图

Dora-moveit 机械臂

GEN72 多视角拍摄系统 - 基于 Dora-rs 数据流架构的完整机械臂控制系统,用于工业管道检测,支持 MuJoCo 仿真和真实机器人。

Project Effect

概述

该系统实现了自动化多视点摄影的管道检测任务。机械臂移动到预定义的视点,拍摄图像,然后返回原位 - 全程采用无碰撞运动规划。

主要特性

  • 双模式运行:MuJoCo 仿真 + 真实 GEN72 机器人支持
  • 高级逆运动学:TracIK 求解器,成功率约 95%
  • 碰撞检测
    • 几何碰撞(球体、盒子、圆柱体)
    • 3D LiDAR 点云集成(已准备好,默认禁用)
    • Realman SDK 碰撞检测框架
  • 多视角拍摄:自动化 3 视点摄影工作流
  • 平滑运动:可配置速度的轨迹插值
  • 保持逻辑:运动完成后防止控制漂移

文档导航

介绍

系统架构

┌─────────────────────────────────────────────────────────────────┐
│                    GEN72 System Architecture                     │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   multi_view_capture_node.py (Workflow Controller)             │
│       │                                                          │
│       ├──► ik_op.py (TracIK Solver)                            │
│       │         └──► Cartesian pose → Joint angles             │
│       │                                                          │
│       ├──► planner_ompl_with_collision_op.py (RRT-Connect)     │
│       │         ├──► Collision-free path planning              │
│       │         └──► Point cloud + geometric collision         │
│       │                                                          │
│       ├──► trajectory_executor.py (Interpolation)              │
│       │         └──► Smooth waypoint interpolation             │
│       │                                                          │
│       └──► Robot Control Node                                   │
│             ├──► MuJoCo Simulator (main.py)                    │
│             └──► Real GEN72 Robot (gen72_robot_node.py)        │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

文件结构

dora-moveit/
├── run_mujoco.bat                    # 启动 MuJoCo 仿真
├── run_real_robot.bat                # 启动真实机器人控制
│
├── dataflow_gen72_mujoco.yml         # MuJoCo 数据流配置
├── dataflow_gen72_real.yml           # 真实机器人数据流配置
│
├── multi_view_capture_node.py        # 主工作流控制器
├── trajectory_executor.py            # 轨迹插值
├── ik_op.py                          # TracIK 逆运动学
├── planner_ompl_with_collision_op.py # RRT-Connect 运动规划器
├── planning_scene_op.py              # 场景管理
│
├── gen72_robot_node.py               # 真实机器人控制(Realman SDK)
├── robot_config.py                   # GEN72 参数与碰撞几何
│
├── rm_robot_interface.py             # Realman SDK 接口
├── rm_ctypes_wrap.py                 # Realman SDK C 包装器
├── api_c.dll                         # Realman SDK 库
│
├── requirements.txt                  # Python 依赖
├── README.md                         # 说明文件
└── RELEASE.md                        # 版本历史

性能指标

指标MuJoCo真实机器人
IK 成功率~95%~95%
规划时间0.05-0.15s0.05-0.15s
运动速度1.0 waypoint/s0.25 waypoint/s
控制频率20 Hz5 Hz
典型工作流时间~30s~60s

快速开始

环境准备

# Python 环境
conda create -n dora-moveit python=3.9
conda activate dora-moveit

# 安装依赖
pip install -r requirements.txt

# 安装 Dora
pip install dora-rs

# 安装 MuJoCo(用于仿真)
pip install mujoco
pip install -e dora-mujoco/

运行仿真

# 启动 MuJoCo 仿真
./run_mujoco.bat

# 或手动执行:
dora up
dora build dataflow_gen72_mujoco.yml
dora start dataflow_gen72_mujoco.yml

运行效果

  1. MuJoCo 窗口打开,GEN72 机器人在 HOME 位置
  2. 系统规划到 3 个视点的无碰撞路径
  3. 机器人在每个视点拍摄图像
  4. 返回 HOME 并进入空闲状态

运行真实机器人

重要:确保机器人已上电,工作区域清空,紧急停止按钮可触及。

# 启动真实机器人控制
./run_real_robot.bat

# 或手动执行:
dora up
dora build dataflow_gen72_real.yml
dora start dataflow_gen72_real.yml

故障排除

MuJoCo 问题

问题:“Model not found” 错误

# 解决方案:设置 MODEL_NAME 环境变量
export MODEL_NAME="path/to/GEN72_with_actuators.xml"

问题:Joint1 在完成后仍然旋转

# 解决方案:检查 HOLD 逻辑超时
# 在 main.py 中: self.cmd_timeout = 0.2  # 如需增加

真实机器人问题

问题:连接失败

# 检查:
# 1. 机器人已上电
# 2. 网络连接(ping 192.168.1.19)
# 3. 防火墙设置
# 4. SDK DLL 在正确路径

问题:机器人运动不平滑

# 解决方案:调整控制频率
# 在 dataflow_gen72_real.yml 中:
tick: dora/timer/millis/200  # 增加以获得更平滑的运动

安全指南

运行真实机器人前

  1. 电源检查:确保机器人已上电并初始化
  2. 工作区域:清除机器人工作区域内的所有障碍物
  3. 紧急停止:确认紧急停止按钮可触及
  4. 限位:确认关节限位正确配置
  5. 速度:测试时从低速(10%)开始

紧急程序

  • 立即停止:按紧急停止按钮
  • 软件停止:在终端按 Ctrl+C
  • 断电:使用主电源开关

碰撞避免

  • 系统使用 10mm 安全边距
  • 地平面在 z=-0.05m
  • 自碰撞检查已启用
  • 相邻连杆(±1)跳过以增加灵活性

系统配置

GEN72 机器人参数

  • 自由度(DOF):7 关节
  • HOME 位置[0.0, -0.5, 0.0, 0.0, 0.0, 0.5, 0.0](弧度)
  • IP 地址:192.168.1.19:8080
  • 控制模式:通过 Realman SDK 的位置控制

拍摄视点

multi_view_capture_node.py 中定义:

targets = [
    CaptureTarget("view1", [0.4, 0.2, 0.5]),   # 右视点
    CaptureTarget("view2", [0.4, -0.2, 0.5]),  # 左视点
    CaptureTarget("view3", [0.5, 0.0, 0.4])    # 中心视点
]

添加新视点

编辑 multi_view_capture_node.py

self.targets = [
    CaptureTarget("view1", [0.4, 0.2, 0.5]),
    CaptureTarget("view4", [0.3, 0.3, 0.6]),  # 添加新视点
]

控制频率

模式频率插值速度
MuJoCo 仿真20 Hz (50ms)0.05
真实机器人5 Hz (200ms)0.05

调整运动速度

仿真dataflow_gen72_mujoco.yml):

tick: dora/timer/millis/50  # 减小以加快速度

真实机器人dataflow_gen72_real.yml):

tick: dora/timer/millis/200  # 减小以加快速度(最小:50ms)

插值trajectory_executor.py):

self.interpolation_speed = 0.05  # 增加以加快速度(最大:0.2)

真实机器人速度gen72_robot_node.py):

self.robot.rm_movej(joint_deg, 10, ...)  # 增加 10%(最大:100%)

碰撞球体配置

robot_config.py 中定义:

link_spheres = {
    "link1": [([0, 0, 0.1], 0.08)],
    "link2": [([0, 0, 0.15], 0.07)],
    ...
}

启用点云碰撞

  1. 确保点云数据可用
  2. 修改 planner_ompl_with_collision_op.py
self.use_point_cloud = True
  1. 在数据流中连接点云输入

组件详情

multi_view_capture_node.py

工作流控制器,协调整个拍摄序列。

输入

  • joint_positions:当前机器人状态
  • ik_solution, ik_status:IK 求解器结果
  • trajectory, plan_status:运动规划器结果
  • execution_status:轨迹执行反馈

输出

  • ik_request:IK 的目标位姿
  • plan_request:运动规划请求
  • scene_command:场景更新

状态机

  1. idle → 请求视点的 IK
  2. waiting_for_ik → 请求运动规划
  3. waiting_for_planning → 等待轨迹
  4. waiting_for_execution → 监控执行
  5. capturing → 拍摄图像
  6. 对所有视点重复
  7. returning_home → 返回 HOME
  8. idle → 完成

trajectory_executor.py

在航点之间插值以实现平滑运动。

关键参数

  • interpolation_speed:0.05(每个周期 5% 进度)
  • tick_rate:50ms(MuJoCo)/ 200ms(真实机器人)

功能特性

  • 航点之间的线性插值
  • HOLD 模式:空闲时返回当前关节状态
  • 防止轨迹完成后的控制漂移

ik_op.py

基于 TracIK 的逆运动学求解器。

求解器:TracIK(高级,成功率约 95%)

备用:数值 IK(阻尼最小二乘)

输入:6D 位姿 [x, y, z, roll, pitch, yaw]

输出:7D 关节配置


planner_ompl_with_collision_op.py

带碰撞检测的 RRT-Connect 运动规划器。

算法:RRT-Connect(双向 RRT)

碰撞边距:10mm 安全缓冲

最大规划时间:5 秒

碰撞检测

  • 自碰撞检查(跳过相邻连杆)
  • 环境碰撞(障碍物、地平面)
  • 点云碰撞(框架已准备好)

gen72_robot_node.py

通过 Realman SDK 的真实机器人控制。

连接

  • IP:192.168.1.19:8080
  • 线程模式:三线程(mode=2)
  • 级别:3

单位转换

  • 系统内部使用弧度
  • SDK 使用角度
  • 自动转换:np.deg2rad() / np.rad2deg()

控制

  • 命令:rm_movej(joints_deg, speed=10%, r=0, connect=0, block=1)
  • 更新频率:5 Hz(200ms tick)

robot_config.py

GEN72 机器人配置:

参数

  • 关节限位、HOME 位置、URDF 路径
  • 碰撞几何(每个连杆的球体)
  • 连杆尺寸和偏移

关键修复记录

1. MuJoCo 控制漂移(已修复)

问题:工作流完成后 Joint1 继续旋转。

根本原因:MuJoCo 的 PD 控制器使用过时的目标位置,导致持续的误差累积。

解决方案:在 main.py:127-137 中实现基于超时的 HOLD 逻辑:

if now - self.last_cmd_time > self.cmd_timeout:
    self.data.ctrl[:self.num_joints] = current_q  # 强制 HOLD

2. 轨迹执行器漂移(已修复)

问题:空闲时执行器返回过时的航点位置。

解决方案:修改 trajectory_executor.py:step() 以返回当前关节状态:

if not self.is_executing:
    return self.current_joints.copy()  # 不是 last_command

3. 真实机器人 API 集成(已修复)

问题:连接失败和不正确的 API 使用。

解决方案

  • 使用 rm_thread_mode_e(2) 作为线程模式
  • 检查 handle.id == -1 以确定连接错误
  • 解析元组返回值:result[1].joint
  • 添加角度/弧度转换

参考资料