redf
stands for "ROS Endpoint Definition Format", it defines a yaml format which describes the endpoints of a ROS system.
redf
currently supports humble and iron.
A common problem of ROS is that it only contains message definitions, there is no definition of the topics available and their QoS settings expected. redf
aims to solve this by defining the endpoints in a yaml file and generating code so that other packages will not have wrong topics and mismatched QoS.
Currently redf
can:
- Generate a rclcpp based ROS package with the topics, services, actions and their QoS
Other planned features includes:
- Generate documentations
- Generate a rclpy based package
- Integrate with the rosidl codegen
- Integrate with rcl
An example redf file
title: Test Api
description: test api
version: 0.0.1
maintainers:
- name: example
email: example@example.com
license: Apache License 2.0
endpoints:
- title: My Sensor
type: topic
topic: my_sensor
message_type: std_msgs/msg/String
description: Example sensor topic
qos: sensor_data
Generate a ROS package from the yaml
redf --out=out --gen=cpp example.yaml
This will generate a full, ready-to-use ROS package, it can be included into a colcon workspace and be used by other packages.
An example of using the endpoint definitions:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
project(test_node)
find_package(rclcpp REQUIRED)
find_package(test_api REQUIRED)
add_executable(test_node main.cpp)
target_link_libraries(test_node rclcpp::rclcpp test_api::test_api)
test_api
automatically brings in the required messages.
main.cpp:
#include <test_api.hpp>
#include <rclcpp/rclcpp.hpp>
int main(int argc, char* argv[]) {
rclcpp::init(argc, argv);
auto test_node = rclcpp::Node::make_shared("test_node");
using test_api::MySensor;
auto pub = test_node->create_publisher<MySensor::MessageType>(MySensor::topic_name(), MySensor::qos());
MySensor::MessageType msg;
msg.data = "hello";
pub->publish(msg);
return 0;
}
MessageType
is a alias to the message type used for the topic (in this case, it isstd_msgs/msg/String
).topic_name()
returns astd::string
with the topic name of the endpoint.qos()
returns therclcpp::QoS
of the endpoint.
Example for service clients:
#include <test_api.hpp>
#include <rclcpp/rclcpp.hpp>
int main(int argc, char* argv[]) {
rclcpp::init(argc, argv);
auto test_node = rclcpp::Node::make_shared("test_node");
using test_namespace::test_api::TestService;
auto client = test_node->create_client<TestService::ServiceType>(TestService::service_name());
auto req = std::make_shared<TestService::ServiceType::Request>();
client->async_send_request(req);
return 0;
}
ServiceType
is a alias to the message type used for the topic (in this case, it isexample_interfaces/srv/AddTwoInts
).service_name()
returns astd::string
with the service name of the endpoint.- The default service qos will be used.
For more examples, see https://github.com/ros2/examples, usages with redf
is the same, just replace the message types, strings and qos with those from the generated library.
The full format of redf
is available as a json schema here.
You can also generate the schema from source with
cargo run -F json_schema --bin generate-schema
Sometimes a system may use namespaced topics to separate the channels between similar nodes. For example, a camera array may publish their images to /camera_0/image_raw
, /camera_1/image_raw
... etc. This can be represented with redf via variable subsitution.
- title: Camera Images
type: topic
description: Raw camera images
topic: '/{camera_id}/image_raw'
message_type: sensor_msgs/msg/Image
When redf generates code for this endpoint, it will have an argument in the topic_name
function, e.g.
static inline std::string topic_name(const std::string& camera_id) {
const std::string topic = "/" + camera_id + "/image_raw";
return topic;
}
This also works for service and action names.
-
Install the yaml extension https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml
-
Edit your vscode settings to include this
"yaml.schemas": {
"https://raw.githubusercontent.com/osrf/redf/main/redf.schema.json": "*.redf.yaml"
}
- Make sure your filename ends with
.redf.yaml
.
You should now have code completion for redf
Requirements:
- supported ros distro
- rosdeps
- ament_cmake
- std_msgs
- example_interfaces
- rclcpp
- rclcpp_action
Use rosdep
to resolve and install the dependencies
rosdep resolve -q ament_cmake std_msgs example_interfaces rclcpp rclcpp_action | sed '/^#/d' | xargs sudo apt install
Source ROS and run the tests
. /opt/ros/{DISTRO}/setup.bash && cargo test