您的位置:首页 > 教育 > 培训 > Fast-DDS ros2 ros与fastdds通讯

Fast-DDS ros2 ros与fastdds通讯

2024/10/6 12:19:48 来源:https://blog.csdn.net/surfaceyan/article/details/140621317  浏览:    关键词:Fast-DDS ros2 ros与fastdds通讯

系列文章目录

  


文章目录

  • 系列文章目录
  • 前言
  • 一、创建用户自定义的msg和srv文件
    • 1. 创建用于接口的package
    • 2. 修改ros相关的配置文件
    • 3. 构建ros_dds_comm_interface包
  • 二、编写pub/sub程序
  • 三、配置discovery server
  • 四、编写fastrtps程序
  • 五、配置ros与远程fastdds程序连接
      • ros端
      • 远程
  • 注意项
  • references


前言

本文介绍了ros环境中的节点与无ros环境程序之间的通讯。
ros = plumbing + tools + capabilities + community
其中plumbing采用DDS协议,ros2默认其中Fast-DDS,因此ros2节点默认是通过fastdds与其他节点(应用)进行通讯的,本文介绍的是在ros2环境下编写的节点与远程主机无ros环境通过fastrtps库编写的程序之间的通讯。


一、创建用户自定义的msg和srv文件

ros2中的类型与C++, python, DDS type 之间的对应关系
https://docs.ros.org/en/humble/Concepts/Basic/About-Interfaces.html

1. 创建用于接口的package

该文件是DDS与ros2节点之间通讯的接口文件
.msg:

string name
uint32 second
uint32 nanosecond
uint32 payload_size
byte[] payload

在ros中新建接口文件:

ros2 pkg create --build-type ament_cmake --license Apache-2.0 ros_dds_comm_interface

切换至ros_dds_comm_interface目录,并创建.msg文件放入msg目录内:

cd ros_dds_comm_interface
mkdir msg
cd msg
touch DdsEvt.msg  # 将上面.msg的内容填入

2. 修改ros相关的配置文件

在包ros_dds_comm_interface内修改:

CMakeLists.txt内的find_package(ament_cmake REQUIRED)下一行添加

find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}"msg/DdsEvt.msg"# DEPENDENCIES geometry_msgs # Add packages that above messages depend on, in this case geometry_msgs for Sphere.msg
)

在package.xml的<package>标签下添加:

  <!-- <depend>geometry_msgs</depend> --><buildtool_depend>rosidl_default_generators</buildtool_depend><exec_depend>rosidl_default_runtime</exec_depend><member_of_group>rosidl_interface_packages</member_of_group>

3. 构建ros_dds_comm_interface包

cd <your ros root dir>
colcon build --packages-select ros_dds_comm_interface

这一步会生成支持C++和Python的接口文件,即可用Python使用该接口也可用C++。

二、编写pub/sub程序

在目录build/ros_dds_comm_interface/rosidl_adapter/ros_dds_comm_interface/msg下找到DdsEvt.idl文件,其内容如下:

module ros_dds_comm_interface {module msg {struct DdsEvt {string name;uint32 second;uint32 nanosecond;uint32 payload_size;sequence<octet> payload;};};
};

通过该idl文件生成fastdds接口代码

fastddsgen -example CMake -typeros2 -d <target_dir> DdsEvt.idl

需要注意,先找到接口包生成的头文件<workspace>/build/ros_dds_comm_interface/rosidl_generator_cpp/ros_dds_comm_interface/msg/dds_evt.hpp该文件就是从.msg生成的头文件,文件名为DdsEvt.msg生成的头文件os_dds_comm_interface/msg/dds_evt.hpp,类名DdsEvt

publisher.cpp

#include <chrono>
#include <functional>
#include <memory>
#include <string>#include "rclcpp/rclcpp.hpp"
#include "ros_dds_comm_interface/msg/dds_evt.hpp"using namespace std::chrono_literals;/* This example creates a subclass of Node and uses std::bind() to register a* member function as a callback from the timer. */class MinimalPublisher : public rclcpp::Node
{
public:MinimalPublisher(): Node("minimal_publisher"), count_(0){publisher_ = this->create_publisher<ros_dds_comm_interface::msg::DdsEvt>("InterfaceTestTopic", 10);timer_ = this->create_wall_timer(500ms, std::bind(&MinimalPublisher::timer_callback, this));}private:void timer_callback(){auto message = ros_dds_comm_interface::msg::DdsEvt();// std_msgs::msg::String();message.name = "Hello, world! " + std::to_string(count_);message.second = count_++;RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.name.c_str());publisher_->publish(message);}rclcpp::TimerBase::SharedPtr timer_;rclcpp::Publisher<ros_dds_comm_interface::msg::DdsEvt>::SharedPtr publisher_;size_t count_;
};int main(int argc, char * argv[])
{rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<MinimalPublisher>());rclcpp::shutdown();return 0;
}

subscriber.cpp

#include <functional>
#include <memory>#include "rclcpp/rclcpp.hpp"
#include "ros_dds_comm_interface/msg/dds_evt.hpp"                                       // CHANGEusing std::placeholders::_1;class MinimalSubscriber : public rclcpp::Node
{
public:MinimalSubscriber(): Node("minimal_subscriber"){subscription_ = this->create_subscription<ros_dds_comm_interface::msg::DdsEvt>(    // CHANGE"InterfaceTestTopic", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1));}private:void topic_callback(const ros_dds_comm_interface::msg::DdsEvt & msg) const  // CHANGE{RCLCPP_INFO_STREAM(this->get_logger(), "I heard: '" << msg.name << "'");     // CHANGE}rclcpp::Subscription<ros_dds_comm_interface::msg::DdsEvt>::SharedPtr subscription_;  // CHANGE
};int main(int argc, char * argv[])
{rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<MinimalSubscriber>());rclcpp::shutdown();return 0;
}

修改cmake文件:

find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(ros_dds_comm_interface REQUIRED)add_executable(talker src/publisher.cpp)
ament_target_dependencies(talker rclcpp ros_dds_comm_interface)
add_executable(listener src/subscriber.cpp)
ament_target_dependencies(listener rclcpp ros_dds_comm_interface)install(TARGETStalkerlistenerDESTINATION lib/${PROJECT_NAME})

修改xml文件:

  <buildtool_depend>ament_cmake</buildtool_depend><depend>ros_dds_comm_interface</depend>

构建并验证是否正常

cd <workspace>
colcon build

on one terminal:

source install/setup.bash
ros2 run cpp_pubsub talker

on another terminal:

source install/setup.bash
ros2 run cpp_pubsub listener

此时两个终端应该能看到数据收发

三、配置discovery server

在一个新终端中开启discovery服务

fastdds discovery -i 0 -l 0.0.0.0 -p 11811
# 输入fastdds discovery -h有更多帮助信息

如果服务在本机上,则需要设置下面的地址为127.0.0.1

talker终端:

export ROS_DISCOVERY_SERVER=127.0.0.1:11811
ros2 run cpp_pubsub talker

listener终端:

export ROS_DISCOVERY_SERVER=127.0.0.1:11811
ros2 run cpp_pubsub listener

此时应该能看到两个终端的收发。

此时ros2 topic list不能看到对应topic,需要开启SUPER_CLIENT模式,具体详见下面的references
5 ros2 检视

export FASTRTPS_DEFAULT_PROFILES_FILE=<path/to/>super_client_configuration_file.xml

四、编写fastrtps程序

相关库安装见:https://blog.csdn.net/surfaceyan/article/details/137162608

在ros2中显示的topic为InterfaceTestTopic,fastdds中对应的topic为rt/InterfaceTestTopic,data type通过工具生成已经填入为ros_dds_comm_interface::msg::dds_::DdsEvt_

据此修改例子:https://github.com/eProsima/Fast-DDS/tree/master/examples/cpp/discovery_server

五、配置ros与远程fastdds程序连接

ros端

new terminal

fastdds discovery -i 0 -l 0.0.0.0 -p 11811

new terminal

# udpv4
export ROS_DISCOVERY_SERVER=127.0.0.1:11811
ros2 run cpp_pubsub talker
export ROS_DISCOVERY_SERVER=TCPv4:[127.0.0.1]:42100

远程

./DiscoveryServerExample publisher -c <ros主机ip> -p <fastdds discovery端口号:11811 >

此时应该能看到ros2节点和远程无ros主机进行通讯

以固定周期发送数据:

yes | while read line; do echo "$line"; sleep 0.01; done | ./DdsEvt publisher

注意项

不同版本的DDS存在兼容性问题。
需要注意要保持通讯实体之间用相同的DDS版本

根据topic所属的ROS2子系统,ROS 2 会向DDS中的topic添加特殊的token。更多信息请参考references [6, 7]。

有关fastddsgen的选项参考[5]


references

  1. https://github.com/briancaglioni/FASTDDS_ROS2_Pub_Sub_Guide
  2. https://docs.ros.org/en/humble/Concepts/Basic/About-Interfaces.html
  3. https://docs.ros.org/en/humble/Tutorials/Advanced/Discovery-Server/Discovery-Server.html
  4. https://fast-dds.docs.eprosima.com/en/stable/fastdds/ros2/discovery_server/ros2_discovery_server.html
  5. https://fast-dds.docs.eprosima.com/en/latest/fastddsgen/usage/usage.html
  6. https://fast-dds.docs.eprosima.com/en/stable/fastdds/use_cases/rosbag_capture/rosbag_capture.html
  7. https://design.ros2.org/articles/topic_and_service_names.html#examples-of-ros-names-to-dds-concepts

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com