Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update master in rmw_iceoryx for rolling #55

Merged
merged 9 commits into from
Aug 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .github/workflows/additional_repos.repos

This file was deleted.

8 changes: 4 additions & 4 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ on:
jobs:
lint:
name: ament_${{ matrix.linter }}
runs-on: ubuntu-18.04
runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
linter: [cppcheck, cpplint, uncrustify, xmllint, copyright]
steps:
- uses: actions/checkout@v1
- uses: ros-tooling/setup-ros@0.0.23
- uses: ros-tooling/action-ros-lint@0.0.6
- uses: actions/checkout@v2
- uses: ros-tooling/setup-ros@master
- uses: ros-tooling/action-ros-lint@master
with:
linter: ${{ matrix.linter }}
package-name: |
Expand Down
13 changes: 7 additions & 6 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,17 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-18.04]
os: [ubuntu-20.04]
steps:
- uses: actions/checkout@v2
- name: Setup ROS
uses: ros-tooling/setup-ros@0.0.23
uses: ros-tooling/setup-ros@master
with:
required-ros-distributions: rolling
- name: Install Iceoryx Dependencies
run: sudo apt-get update && sudo apt-get install -y cmake libacl1-dev libncurses5-dev pkg-config
- name: Build & Test
uses: ros-tooling/action-ros-ci@0.0.17
uses: ros-tooling/action-ros-ci@master
with:
package-name: rmw_iceoryx_cpp iceoryx_ros2_bridge
vcs-repo-file-url: |
https://gist.githubusercontent.com/Karsten1987/1723f219bb5aa5b81355c7eb1477f867/raw/9dc4d877f6fd0f862070516febdbddea28723b5c/iceoryx.repos
https://raw.githubusercontent.com/ros2/ros2/master/ros2.repos
target-ros2-distro: rolling
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
*.swp
.vscode/
build/
install/
log/
rclcpp/
39 changes: 32 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ Installation

The following instructions show you how to install [iceoryx](https://github.com/eclipse/iceoryx) and its rmw implementation.
The installation of iceoryx and rmw_iceoryx is pretty straight forward.
All provided packages can be built with colcon so that you can easily build both, iceoryx and rmw_iceoryx, within your ROS2 workspace.
rmw_iceoryx is using the [rosidl_typesupport_introspection](https://github.com/ros2/rosidl) which allows for building iceoryx on top of an existing ROS2 workspace or even debian installation as no ROS2 messages have to be built again.
All provided packages can be built with colcon so that you can easily build both, iceoryx and rmw_iceoryx, within your ROS 2 workspace.
rmw_iceoryx is using the [rosidl_typesupport_introspection](https://github.com/ros2/rosidl) which allows for building iceoryx on top of an existing ROS2 workspace or even debian installation as no ROS 2 messages have to be built again.

To install iceoryx and rmw_iceoryx in a ROS2 workspace, just execute the steps below:
To install iceoryx and rmw_iceoryx in a ROS 2 workspace, just execute the steps below:

```
mkdir -p ~/iceoryx_ws/src
Expand All @@ -20,13 +20,15 @@ git clone https://github.com/ros2/rmw_iceoryx.git
```
For alternative installation instructions and more details about iceoryx's internals, please see [iceoryx's GitHub repo](https://github.com/eclipse/iceoryx).

rmw_iceoryx is compatible with ROS2 Eloquent.
rmw_iceoryx is compatible with ROS 2 Galactic.
Assuming you have ROS2 installed correctly, you can compile the iceoryx workspace with colcon:

```
cd ~/iceoryx_ws/
source /opt/ros/eloquent/setup.bash # alternatively source your own ROS2 workspace
source /opt/ros/galactic/setup.bash # alternatively source your own ROS 2 workspace
colcon build
# or with more options
colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF
```

That's it! You've installed iceoryx and are ready to rumble.
Expand Down Expand Up @@ -82,7 +84,7 @@ rmw_iceoryx_cpp gives a loaned message to the subscription which can execute the

Step 4 `return_loaned_message()`) A subscription callback is finished and the loaned message is getting returned to the middleware.

Starting from ROS2 Eloquent, these features are implemented within rclcpp.
Starting from ROS 2 Eloquent, these features are implemented within rclcpp.
An application using these new features is shown in the code snippet below.
For a fully working implementation, please have a look at [this demo node](https://github.com/ros2/demos/blob/master/demo_nodes_cpp/src/topics/talker_loaned_message.cpp).

Expand Down Expand Up @@ -123,4 +125,27 @@ Limitations

rmw_iceoryx_cpp is currently under heavy development.
Unfortunately, not all features are yet fully fleshed out.
Other core functionalities like e.g. services are not yet implemented, but will follow soon.

| ROS 2 command/feature | Status |
|-----------------------|------------------------------------|
| `ros2 topic list` | :heavy_check_mark: |
| `ros2 topic echo` | :heavy_check_mark: |
| `ros2 topic type` | :heavy_check_mark: |
| `ros2 topic info` | :heavy_check_mark: |
| `ros2 topic hz` | :heavy_check_mark: |
| `ros2 topic bw` | :heavy_check_mark: |
| `ros2 node list` | :heavy_check_mark: |
| `ros2 node info` | :heavy_check_mark: |
| `ros2 interface *` | :heavy_check_mark: |
| `ros2 service *` | :x: (coming with iceoryx v2.0) |
| `ros2 param list` | :x: (coming with iceoryx v2.0) |
| `rqt_graph` | :heavy_check_mark: |
| `rqt_top` | :heavy_check_mark: |
| `rqt_console` | :heavy_check_mark: |
| `rqt_plot` | :heavy_check_mark: |
| `rviz2` | :heavy_check_mark: |
| `ros2 bag` | :grey_question: |
| urdf | :grey_question: |
| tf2 | :grey_question: |
| ROS 2 bridge | :grey_question: |
| RMW Pub/Sub Events | :x: |
9 changes: 9 additions & 0 deletions iceoryx_ros2_bridge/src/generic_subscription.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright 2018, Bosch Software Innovations GmbH.
// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -88,6 +89,14 @@ void GenericSubscription::return_serialized_message(
message.reset();
}

void GenericSubscription::handle_serialized_message(
const std::shared_ptr<rclcpp::SerializedMessage> & serialized_message,
const rclcpp::MessageInfo & message_info)
{
(void) serialized_message;
(void) message_info;
}

void GenericSubscription::handle_loaned_message(
void * loaned_message,
const rclcpp::MessageInfo & message_info)
Expand Down
5 changes: 5 additions & 0 deletions iceoryx_ros2_bridge/src/generic_subscription.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright 2018, Bosch Software Innovations GmbH.
// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -79,6 +80,10 @@ class GenericSubscription : public rclcpp::SubscriptionBase

void return_serialized_message(std::shared_ptr<rclcpp::SerializedMessage> & message) override;

void handle_serialized_message(
const std::shared_ptr<rclcpp::SerializedMessage> & serialized_message,
const rclcpp::MessageInfo & message_info);

void handle_loaned_message(
void * loaned_message, const rclcpp::MessageInfo & message_info) override;

Expand Down
79 changes: 51 additions & 28 deletions iceoryx_ros2_bridge/src/iceoryx_ros2_bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
#include <string>
#include <vector>

#include "iceoryx_posh/popo/publisher.hpp"
#include "iceoryx_posh/popo/subscriber.hpp"
#include "iceoryx_posh/popo/untyped_publisher.hpp"
#include "iceoryx_posh/popo/untyped_subscriber.hpp"
#include "iceoryx_posh/runtime/posh_runtime.hpp"

#include "rclcpp/rclcpp.hpp"
Expand Down Expand Up @@ -61,21 +61,26 @@ bool deserialize_into(
void publish_to_iceoryx(
std::shared_ptr<rclcpp::SerializedMessage> serialized_msg,
const rosidl_message_type_support_t * ts,
std::shared_ptr<iox::popo::Publisher> iceoryx_publisher)
std::shared_ptr<iox::popo::UntypedPublisher> iceoryx_publisher)
{
auto introspection_ts = static_cast<const rosidl_typesupport_introspection_cpp::MessageMembers *>(
get_message_typesupport_handle(
ts, rosidl_typesupport_introspection_cpp::typesupport_identifier)->data);

if (rmw_iceoryx_cpp::iceoryx_is_fixed_size(ts)) {
void * ros_msg = iceoryx_publisher->allocateChunk(introspection_ts->size_of_);
introspection_ts->init_function(ros_msg, rosidl_runtime_cpp::MessageInitialization::ALL);

if (false == deserialize_into(serialized_msg.get(), ts, ros_msg)) {
iceoryx_publisher->freeChunk(ros_msg);
return;
}
iceoryx_publisher->sendChunk(ros_msg);
iceoryx_publisher->loan(introspection_ts->size_of_)
.and_then(
[&, introspection_ts](void * ros_msg) {
introspection_ts->init_function(ros_msg, rosidl_runtime_cpp::MessageInitialization::ALL);
if (false == deserialize_into(serialized_msg.get(), ts, ros_msg)) {
iceoryx_publisher->release(ros_msg);
}
iceoryx_publisher->publish(ros_msg);
})
.or_else(
[](iox::popo::AllocationError) {
RMW_SET_ERROR_MSG("rmw_borrow_loaned_message error!");
});
} else {
void * ros_msg = malloc(introspection_ts->size_of_);
introspection_ts->init_function(ros_msg, rosidl_runtime_cpp::MessageInitialization::ALL);
Expand All @@ -91,9 +96,12 @@ void publish_to_iceoryx(
payload_vector);
free(ros_msg);

void * chunk = iceoryx_publisher->allocateChunk(payload_vector.size(), true);
memcpy(chunk, payload_vector.data(), payload_vector.size());
iceoryx_publisher->sendChunk(chunk);
iceoryx_publisher->loan(payload_vector.size())
.and_then(
[&, payload_vector](void * userPayload) {
memcpy(userPayload, payload_vector.data(), payload_vector.size());
iceoryx_publisher->publish(userPayload);
});
}
}

Expand All @@ -114,19 +122,27 @@ bool serialize_into(
}

void publish_to_ros2(
std::shared_ptr<iox::popo::Subscriber> subscriber,
std::shared_ptr<iox::popo::UntypedSubscriber> subscriber,
const rosidl_message_type_support_t * ts,
std::shared_ptr<iceoryx_ros2_bridge::GenericPublisher> ros2_publisher)
{
rclcpp::SerializedMessage serialized_msg;

const void * chunk = nullptr;
subscriber->getChunk(&chunk);
subscriber->take()
.and_then(
[&](const void * userPayload) {
chunk = userPayload;
})
.or_else(
[](iox::popo::ChunkReceiveResult) {
RMW_SET_ERROR_MSG("No chunk in subscriber");
});

// ROS2 message is now in chunk. Convert to ROS2 message and then to serialized_message
if (rmw_iceoryx_cpp::iceoryx_is_fixed_size(ts)) {
if (false == serialize_into(chunk, ts, &serialized_msg)) {
subscriber->releaseChunk(chunk);
subscriber->release(chunk);
return;
}
} else {
Expand All @@ -144,7 +160,7 @@ void publish_to_ros2(
ros_msg);

if (false == serialize_into(ros_msg, ts, &serialized_msg)) {
subscriber->releaseChunk(chunk);
subscriber->release(chunk);
return;
}
introspection_ts->fini_function(ros_msg);
Expand All @@ -153,7 +169,7 @@ void publish_to_ros2(

fprintf(stderr, "publishing message\n");
ros2_publisher->publish(&serialized_msg.get_rcl_serialized_message());
subscriber->releaseChunk(chunk);
subscriber->release(chunk);
}

void usage()
Expand Down Expand Up @@ -195,14 +211,17 @@ int main(int argc, char ** argv)
start_parameter_event_publisher(
false).enable_topic_statistics(false);
auto node = std::make_shared<rclcpp::Node>(node_name, node_options);
iox::runtime::PoshRuntime::getInstance(std::string("/") + node_name);
iox::runtime::PoshRuntime::initRuntime(
iox::RuntimeName_t(
iox::cxx::TruncateToCapacity,
node_name));

/*
* Subscribe to a ROS2 topic and re-publish into iceoryx
*/
std::vector<std::shared_ptr<iceoryx_ros2_bridge::GenericSubscription>> ros2_subs;
ros2_subs.reserve(input_topics.size());
std::vector<std::shared_ptr<iox::popo::Publisher>> iceoryx_pubs;
std::vector<std::shared_ptr<iox::popo::UntypedPublisher>> iceoryx_pubs;
iceoryx_pubs.reserve(input_topics.size());

rclcpp::sleep_for(2s); // some room for ros2 discovery
Expand All @@ -229,8 +248,9 @@ int main(int argc, char ** argv)
auto service_desc =
rmw_iceoryx_cpp::get_iceoryx_service_description(topic, ts);
iceoryx_pubs.emplace_back(
std::make_shared<iox::popo::Publisher>(
service_desc, iox::cxx::CString100(iox::cxx::TruncateToCapacity, node_name)));
std::make_shared<iox::popo::UntypedPublisher>(
service_desc, iox::popo::PublisherOptions{
0U, iox::NodeName_t(iox::cxx::TruncateToCapacity, node_name)}));
iceoryx_pubs.back()->offer();

std::function<void(std::shared_ptr<rclcpp::SerializedMessage>)> cb =
Expand All @@ -245,7 +265,7 @@ int main(int argc, char ** argv)
/*
* Subscribe to an iceoryx topic and re-publish into ROS2
*/
std::vector<std::shared_ptr<iox::popo::Subscriber>> iceoryx_subs;
std::vector<std::shared_ptr<iox::popo::UntypedSubscriber>> iceoryx_subs;
iceoryx_subs.reserve(output_topics.size());
std::vector<std::shared_ptr<iceoryx_ros2_bridge::GenericPublisher>> ros2_pubs;

Expand Down Expand Up @@ -275,15 +295,18 @@ int main(int argc, char ** argv)

auto service_desc =
rmw_iceoryx_cpp::get_iceoryx_service_description(topic, ts);
/// @todo karsten1987: find a decent queue size instead of 10
iceoryx_subs.emplace_back(
std::make_shared<iox::popo::Subscriber>(
service_desc, iox::cxx::CString100(iox::cxx::TruncateToCapacity, node_name)));
iceoryx_subs.back()->subscribe(10); // TODO(karsten1987): find a decent queue size
std::make_shared<iox::popo::UntypedSubscriber>(
service_desc, iox::popo::SubscriberOptions{
10U, 0U, iox::cxx::string<100>(iox::cxx::TruncateToCapacity, node_name)}));
iceoryx_subs.back()->subscribe();

auto cb =
std::bind(&publish_to_ros2, iceoryx_subs.back(), ts, ros2_pubs.back());

iceoryx_subs.back()->setReceiveHandler(cb);
/// @todo add a listener
// iceoryx_subs.back()->setReceiveHandler(cb);
}

rclcpp::spin(node);
Expand Down
3 changes: 3 additions & 0 deletions rmw_iceoryx_cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ add_library(rmw_iceoryx_name_conversion SHARED
src/internal/iceoryx_name_conversion.cpp
src/internal/iceoryx_type_info_introspection.cpp
src/internal/iceoryx_topic_names_and_types.cpp
src/internal/iceoryx_get_topic_endpoint_info.cpp
)
target_include_directories(rmw_iceoryx_name_conversion
PUBLIC include
Expand Down Expand Up @@ -86,11 +87,13 @@ add_library(rmw_iceoryx_cpp SHARED
src/rmw_guard_condition.cpp
src/rmw_init.cpp
src/rmw_logging.cpp
src/rmw_network_flow_endpoint.cpp
src/rmw_node.cpp
src/rmw_node_info_and_types.cpp
src/rmw_node_names.cpp
src/rmw_publish.cpp
src/rmw_publisher.cpp
src/rmw_qos.cpp
src/rmw_request.cpp
src/rmw_response.cpp
src/rmw_serialize.cpp
Expand Down
11 changes: 11 additions & 0 deletions rmw_iceoryx_cpp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,14 @@ RMW_ICEORYX_CPP
---------------

C++ implementation of the rmw iceoryx middleware interface.

## test

```sh
/usr/local/bin/iox-roudi -l verbose

export RMW_IMPLEMENTATION=rmw_iceoryx_cpp
ros2 run demo_nodes_cpp talker
ros2 run demo_nodes_cpp listener
iox-introspection-client --all
```
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ struct rosidl_message_type_support_t;
namespace rmw_iceoryx_cpp
{

// TODO(karsten1987): This should be `uint8`, really
/// @todo karsten1987: This should be `uint8`, really
void deserialize(
const char * serialized_msg,
const rosidl_message_type_support_t * type_supports,
Expand Down
Loading