Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Dora Node API for C++
Dora supports nodes written in C++ through this API crate.
Build
- Clone the
dorarepository:> git > cd - Build the
dora-node-api-cxxpackage:- This will result in
dora-node-api.handdora-node-api.ccfiles in thetarget/cxxbridge/dora-node-api-cxxdirectory.
- This will result in
- Include the
dora-node-api.hheader file in your source file. - Add the
dora-node-api.ccfile to your compile and link steps.
Build with ROS2 Bridge
Dora features an experimental ROS2 Bridge that enables dora nodes to publish and subscribe to ROS2 topics. To enable the bridge, use these steps:
- Clone the
dorarepository (see above). - Source the ROS2 setup files (see ROS2 docs)
- Optional: Source package-specific ROS2 setup files if you want to use custom package-specific ROS2 messages in the bridge (see ROS2 docs)
- Build the
dora-node-api-cxxpackage with theros2-bridgefeature enabled:- In addition to the
dora-node-api.handdora-node-api.ccfiles, this will place adora-ros2-bindings.hand adora-ros2-bindings.ccfile in thetarget/cxxbridge/dora-node-api-cxxdirectory.
- In addition to the
- Include both the
dora-node-api.hand thedora-ros2-bindings.hheader files in your source file. - Add the
dora-node-api.ccanddora-ros2-bindings.ccfiles to your compile and link steps.
Usage
The dora-node-api.h header provides various functions to interact with Dora.
Init Dora Node
All nodes need to register themselves with Dora at startup.
To do that, call the init_dora_node() function.
The function returns a DoraNode instance, which gives access to dora events and enables sending Dora outputs.
auto dora_node = ;
Receiving Events
The dora_node.events field is a stream of incoming events.
To wait for the next incoming event, call dora_node.events->next():
auto event = dora_node.events->;
The next function returns an opaque DoraEvent type, which cannot be inspected from C++ directly.
Instead, use the following functions to read and destructure the event:
event_type(event)returns aDoraEventType, which describes the kind of event. For example, an event could be an input or a stop instruction.- when receiving a
DoraEventType::AllInputsClosed, the node should exit and not callnextanymore
- when receiving a
- Events of type
DoraEventType::Inputcan be downcasted usingevent_as_input:
The function returns aauto input = ;DoraInputinstance, which has anidanddatafield.- The input
idcan be converted to a C++ string throughstd::string(input.id). - The
dataof inputs is currently of typerust::Vec<uint8_t>. Use the provided methods for reading or converting the data.- Note: In the future, we plan to change the data type to the Apache Arrow data format to support typed inputs.
- The input
Receiving Arrow Inputs
For Arrow-based inputs, you can use the following functions to receive typed data along with metadata:
event_as_arrow_input(event, out_array, out_schema)- Returns only the Arrow array data (original function)event_as_arrow_input_with_info(event, out_array, out_schema)- Returns Arrow array data plus input ID and metadata as JSON
Example using event_as_arrow_input_with_info:
struct ArrowArray c_array;
struct ArrowSchema c_schema;
// Get Arrow array along with input ID and metadata
auto input_info = ;
// Check for errors
if
// Access input ID
std::cout << "Input ID: " << input_info.id << std::endl;
// Access metadata via the provided helper type
auto metadata = ;
std::cout << "Metadata timestamp: " << metadata-> << std::endl;
// Timestamp parameters use i64 nanoseconds since Unix epoch
auto nanos = metadata->;
metadata->;
// Convert to std::chrono::utc_clock::time_point (C++20)
auto tp = ;
auto keys = metadata->;
for
std::cout << "Metadata as JSON: " << << std::endl;
// Import the Arrow array for processing
auto result = ;
std::shared_ptr<arrow::Array> input_array = result.;
The metadata JSON contains:
timestamp- Message timestamp withsecsandnanosfieldstype_info- Arrow type informationparameters- Custom metadata parameters (key-value pairs)
Sending Outputs
Nodes can send outputs using the send_output output function and the dora_node.send_output field.
Note that all outputs need to be listed in the dataflow YAML declaration file, otherwise an error will occur.
Example:
// the data you want to send (NOTE: only byte vectors are supported right now)
std::vector<uint8_t> ;
// create a Rust slice from the output vector
rust::Slice<const uint8_t> ;
// send the slice as output
auto result = ;
// check for errors
auto error = ;
if
Using the ROS2 Bridge
The dora-ros2-bindings.h contains function and struct definitions that allow interacting with ROS2 nodes.
Currently, the bridge supports publishing and subscribing to ROS2 topics.
In the future, we plan to support ROS2 services and ROS2 actions as well.
Initializing the ROS2 Context
The first step is to initialize a ROS2 context:
auto ros2_context = ;
Creating Nodes
After initializing a ROS2 context, you can use it to create ROS2 nodes:
auto node = ros2_context->;
The first argument is the namespace of the node and the second argument is its name.
Creating Topics
After creating a node, you can use one of the create_topic_<TYPE> functions to create a topic on it.
The <TYPE> describes the message type that will be sent on the topic.
The Dora ROS2 bridge automatically creates create_topic_<TYPE> functions for all messages types found in the sourced ROS2 environment.
auto vel_topic = node->;
The first argument is the namespace of the topic and the second argument is its name. The third argument is the QoS (quality of service) setting for the topic. It can be adjusted as desired, for example:
auto qos = ;
qos.durability = Ros2Durability::Volatile;
qos.liveliness = Ros2Liveliness::Automatic;
auto vel_topic = node->;
Publish
After creating a topic, it is possible to publish messages on it. First, create a publisher:
auto vel_publisher = node->;
The returned publisher is typed by the chosen topic. It will only accept messages of the topic's type, otherwise a compile error will occur.
After creating a publisher, you can use the publish function to publish one or more messages.
For example:
geometry_msgs::Twist twist = ;
vel_publisher->;
The geometry_msgs::Twist struct is automatically generated from the sourced ROS2 environment.
Since the publisher is typed, its publish method only accepts geometry_msgs::Twist messages.
Subscriptions
Subscribing to a topic is possible through the create_subscription function on nodes:
auto pose_topic = node->;
auto pose_subscription = node->;
The topic is the topic you want to subscribe to, created using a create_topic_<TYPE> function.
The second argument is the quality of service setting, which can be customized as described above.
The third parameter is the event stream that the received messages should be merged into. Multiple subscriptions can be merged into the same event stream.
Combined Event Streams
Combined event streams enable the merging of multiple event streams into one. The combined stream will then deliver messages from all sources, in order of arrival.
You can create such a event stream from Dora's event stream using the dora_events_into_combined function:
auto event_stream = ;
Alternatively, if you don't want to use Dora, you can also create an empty event stream:
auto event_stream = ;
Note: You should only use empty_combined_events if you're running your executable independent of Dora.
Ignoring the events from the dora_node.events channel can result in unintended behavior.
Receiving Messages from Combined Event Stream
The merged event stream will receive all incoming events of the node, including Dora events and ROS2 messages.
To wait for the next incoming event, use its next method:
auto event = event_stream.;
This returns a event instance of type CombinedEvent, which can be downcasted to Dora events or ROS2 messages.
To handle an event, you should check it's type and then downcast it:
- To check for a Dora event, you can use the
is_dora()function. If it returnstrue, you can downcast the combined event to a Dora event using thedowncast_dorafunction. - ROS2 subscriptions support a
matchesfunction to check whether a combined event is an instance of the respective ROS2 subscription. If it returns true, you can downcast the event to the respective ROS2 message struct using the subscription'sdowncastfunction.
Example:
if
else if
else
Constants
Some ROS2 message definitions define constants, e.g. to specify the values of an enum-like integer field. The Dora ROS2 bridge exposes these constants in the generated bindings as functions.
For example, the STATUS_NO_FIX constant of the NavSatStatus message can be accessed as follows:
;
(Note: Exposing them as C++ constants is not possible because it's not supported by cxx yet.)
Service Clients
To create a service client, use one of the create_client_<TYPE> functions.
The <TYPE> describes the service type, which specifies the request and response types.
The Dora ROS2 bridge automatically creates create_client_<TYPE> functions for all service types found in the sourced ROS2 environment.
auto add_two_ints = node->;
- The first argument is the namespace of the service and the second argument is its name.
- The third argument is the QoS (quality of service) setting for the service.
It can be set to
qos_default()or adjusted as desired, for example:auto qos = ; qos.reliable = true; qos.max_blocking_time = 0.1; qos.keep_last = 1; - The last argument is the combined event stream that the received service responses should be merged into.
Waiting for the Service
In order to achieve reliable service communication, it is recommended to wait until the service is available before sending requests.
Use the wait_for_service() method for that, e.g.:
add_two_ints->
The given node must be the node on which the service was created.
Sending Requests
To send a request, use the send_request method:
add_two_ints->;
The method sends the request asynchronously without waiting for a response. When the response is received, it is automatically sent to the combined event stream that was given on client creation.
Receiving Responses
See the "Receiving Messages from Combined Event Stream" section for how to receive events from the combined event stream.
To check if a received event is a service response, use the matches method.
If it returns true, you can use the downcast method to convert the event to the correct service response type.
Example:
if