• 操作系统:ubuntu22.04
  • IDE:Visual Studio Code
  • 编程语言:C++11
  • ROS版本:2

ROS 2(Robot Operating System 2)采用了Data Distribution Service (DDS)作为其底层通信中间件,以提供灵活且强大的分布式通信能力。与ROS 1使用的基于TCPROS/UDPROS的通信机制不同,ROS 2通过DDS支持更广泛的特性,如发现机制、服务质量(QoS)策略和跨网络的无缝通信等。以下是关于ROS 2中DDS的一些关键点说明:

算法描述

1. DDS简介

DDS是一个由对象管理组(OMG)定义的用于实时系统中的数据分发的中间件标准。它旨在为分布式应用提供高效可靠的数据传输服务,特别适用于需要高可靠性、实时性和可扩展性的环境。
2. ROS 2与DDS的关系

ROS 2通过抽象层封装了对多种DDS实现的支持,允许用户在不同的DDS供应商之间进行选择。这使得ROS 2不仅能够利用DDS提供的高级特性,还能根据具体应用场景的需求选择最适合的DDS实现。
支持的DDS实现包括但不限于:

  • Fast DDS(原eProsima Fast RTPS):ROS 2默认使用的DDS实现。
  • Cyclone DDS:性能优越,社区活跃。
  • RTI Connext 和 ADLINK OpenSplice:商业级解决方案,适用于需要高度可靠性和性能的企业级应用。

3. 使用DDS的优势

  • 自动发现机制:节点可以自动发现网络上的其他参与者,并建立连接,无需手动配置。
  • 服务质量(QoS)策略:提供了丰富的QoS设置选项,允许用户根据需求调整通信行为,例如持久化消息、历史深度、可靠性等。
  • 多语言支持:虽然ROS 2主要使用C++和Python,但DDS本身支持多种编程语言,便于集成到异构环境中。
  • 安全性:一些DDS实现提供了加密、身份验证等安全功能,增强了系统的安全性。

4. 如何在ROS 2中选择和配置DDS实现

  • 选择DDS实现:可以通过设置RMW_IMPLEMENTATION环境变量来指定要使用的DDS实现。例如,使用Cyclone DDS:
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
  • 安装DDS实现:通常需要额外安装你想要使用的DDS实现。例如,在Ubuntu上安装Cyclone DDS:
sudo apt update && sudo apt install ros-<ros2-distro>-rmw-cyclonedds-cpp
  • QoS配置:可以在创建发布者、订阅者、客户端或服务时指定QoS策略。以下是一个简单的例子,展示了如何为发布者设置可靠的QoS策略:
    auto qos = rclcpp::QoS(rclcpp::KeepLast(10));
    qos.reliable();
    auto publisher = node->create_publisher<std_msgs::msg::String>("topic_name", qos);

5. 注意事项

  • 兼容性问题:尽管ROS 2设计为与任何符合DDS标准的实现兼容,但在实际操作中可能会遇到某些特定于某个DDS实现的功能或限制。
  • 资源消耗:不同的DDS实现在内存占用、CPU使用等方面可能有所不同,部署前应考虑目标平台的资源限制。
  • 安全性配置:如果需要启用安全性功能,需确保所选的DDS实现支持这些特性,并正确配置相应的安全参数。

通过上述介绍,你应该对ROS 2如何利用DDS进行高效的分布式通信有了基本了解。ROS 2结合DDS的能力,使得开发者能够构建更加复杂、健壮的机器人系统。

DDS示例

下面我将提供一个简单的C++示例,展示如何在ROS 2中使用DDS进行通信。这个例子会包括创建一个发布者和订阅者,并且我们会介绍如何配置一些基本的服务质量(QoS)策略。
示例:发布者与订阅者

准备工作

确保你已经安装了ROS 2以及所需的DDS实现(如Fast DDS或Cyclone DDS)。如果没有,请参考ROS 2官方文档来安装适合你操作系统的版本。
创建包

首先,我们需要创建一个新的ROS 2包来存放我们的示例代码。

cd ~/ros2_ws/src
ros2 pkg create --build-type ament_cmake cpp_ddsdemo --dependencies rclcpp std_msgs

这将在~/ros2_ws/src目录下创建一个名为cpp_ddsdemo的新包,并添加必要的依赖项。
在这里插入图片描述

编写发布者代码

在cpp_ddsdemo包的src目录下创建一个名为talker.cpp的文件,并添加以下代码:

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

class Talker : public rclcpp::Node {
public:
    Talker() : Node( "talker" )
    {
        publisher_ = this->create_publisher< std_msgs::msg::String >( "chatter", 10 );

        auto qos_profile = rclcpp::QoS( rclcpp::KeepLast( 10 ) );
        qos_profile.reliable();

        timer_ = this->create_wall_timer( std::chrono::milliseconds( 500 ), std::bind( &Talker::publish_message, this ) );
    }

private:
    void publish_message()
    {
        auto message = std_msgs::msg::String();
        message.data = "Hello, DDS!";
        RCLCPP_INFO( this->get_logger(), "Publishing: '%s'", message.data.c_str() );
        publisher_->publish( message );
    }

    rclcpp::Publisher< std_msgs::msg::String >::SharedPtr publisher_;
    rclcpp::TimerBase::SharedPtr timer_;
};

int main( int argc, char* argv[] )
{
    rclcpp::init( argc, argv );
    rclcpp::spin( std::make_shared< Talker >() );
    rclcpp::shutdown();
    return 0;
}

编写订阅者代码

同样地,在src目录下创建另一个名为listener.cpp的文件,并添加以下代码:

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

class Listener : public rclcpp::Node {
public:
    Listener() : Node( "listener" )
    {
        auto qos_profile = rclcpp::QoS( rclcpp::KeepLast( 10 ) );
        qos_profile.reliable();

        subscription_ = this->create_subscription< std_msgs::msg::String >( "chatter", qos_profile, std::bind( &Listener::topic_callback, this, std::placeholders::_1 ) );
    }

private:
    void topic_callback( const std_msgs::msg::String::SharedPtr msg ) const
    {
        RCLCPP_INFO( this->get_logger(), "I heard: '%s'", msg->data.c_str() );
    }

    rclcpp::Subscription< std_msgs::msg::String >::SharedPtr subscription_;
};

int main( int argc, char* argv[] )
{
    rclcpp::init( argc, argv );
    rclcpp::spin( std::make_shared< Listener >() );
    rclcpp::shutdown();
    return 0;
}

运行演示

base) dingxin@dev01:/media/dingxin/data/projects/ros2/ros2_ws$ colcon build --packages-select cpp_ddsdemo
Starting >>> cpp_ddsdemo
Finished <<< cpp_ddsdemo [0.10s]                  

Summary: 1 package finished [0.25s]
(base) dingxin@dev01:/media/dingxin/data/projects/ros2/ros2_ws$ source install/setup.bash
(base) dingxin@dev01:/media/dingxin/data/projects/ros2/ros2_ws$ ros2 run cpp_ddsdemo talker &
ros2 run cpp_ddsdemo listener
[1] 1160036
[INFO] [1748245206.358214598] [talker]: Publishing: 'Hello, DDS!'
[INFO] [1748245206.358651899] [listener]: I heard: 'Hello, DDS!'
[INFO] [1748245206.858210334] [talker]: Publishing: 'Hello, DDS!'
[INFO] [1748245206.858562915] [listener]: I heard: 'Hello, DDS!'
[INFO] [1748245207.358192083] [talker]: Publishing: 'Hello, DDS!'
[INFO] [1748245207.358469411] [listener]: I heard: 'Hello, DDS!'
[INFO] [1748245207.858307761] [talker]: Publishing: 'Hello, DDS!'
[INFO] [1748245207.858611755] [listener]: I heard: 'Hello, DDS!'
[INFO] [1748245208.358326562] [talker]: Publishing: 'Hello, DDS!'
[INFO] [1748245208.358733223] [listener]: I heard: 'Hello, DDS!'
[INFO] [1748245208.858240497] [talker]: Publishing: 'Hello, DDS!'
[INFO] [1748245208.858584031] [listener]: I heard: 'Hello, DDS!'
[INFO] [1748245209.358235552] [talker]: Publishing: 'Hello, DDS!'
[INFO] [1748245209.358555639] [listener]: I heard: 'Hello, DDS!'
[INFO] [1748245209.858258810] [talker]: Publishing: 'Hello, DDS!'
[INFO] [1748245209.858585246] [listener]: I heard: 'Hello, DDS!'

你应该能看到发布者每半秒发送一次消息,而订阅者接收并打印这些消息。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐