DDS:domain

domain域层架构

域代表一个单独的通信平面。它在共享公共通信基础设施的实体之间创建了逻辑分离。从概念上讲,它可以看作是一个虚拟网络,连接在同一域上运行的所有应用程序,并将它们与运行在不同域上的应用程序隔离开来。这样,多个独立的分布式应用程序可以在同一个物理网络中共存,而不会相互干扰,甚至不会相互感知。

每个域都有一个唯一的标识符,称为 domainId,它被实现为一个uint32值。共享此 domainId 的应用程序属于同一个域并且能够通信。

对于要添加到域的应用程序,它必须创建 具有适当 domainId的DomainParticipant实例。DomainParticipant 的实例是通过 DomainParticipantFactory单例创建的。

分区在域中引入了另一个实体隔离级别。虽然 DomainParticipant 如果它们在同一个域中将能够相互通信,但仍然可以隔离它们的Publishers和 Subscribers并将它们分配给不同的Partitions。
在这里插入图片描述

域参与者

DomainParticipant是应用程序到域的入口点。每个 DomainParticipant 从创建时就链接到单个域,并包含与该域相关的所有实体。它还充当Publisher、Subscriber 和Topic的工厂。

DomainParticipant 的行为可以使用 DomainParticipantQos 上指定的 QoS 值进行修改。QoS 值可以在创建 DomainParticipant 时设置,或者稍后使用DomainParticipant::set_qos()成员函数进行修改。

作为一个实体,DomainParticipant 接受一个DomainParticipantListener ,它将在 DomainParticipant 实例上收到状态更改通知。

域参与者Qos

DomainParticipantQos控制 DomainParticipant 的行为。它在内部包含以下QosPolicy对象:
在这里插入图片描述
可以使用 DomainParticipant::set_qos()成员函数修改先前创建的 DomainParticipant 的 QoS 值。尝试在已启用的 DomainParticipant 上修改不可变的 QosPolicy 将导致错误。在这种情况下,不会应用任何更改,并且 DomainParticipant 将保留其先前的 DomainParticipantQos。

// Create a DomainParticipant with default DomainParticipantQos
DomainParticipant* participant =
        DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT);
if (nullptr == participant)
{
    // Error
    return;
}

// Get the current QoS or create a new one from scratch
DomainParticipantQos qos = participant->get_qos();

// Modify QoS attributes
qos.entity_factory().autoenable_created_entities = false;

// Assign the new Qos to the object
participant->set_qos(qos);

默认 DomainParticipantQos

默认的 DomainParticipantQos 是指DomainParticipantFactoryget_default_participant_qos()单例上的成员函数 返回的值 。该特殊值可用作 QoS 参数 或成员函数,以指示应使用当前默认的 DomainParticipantQos。PARTICIPANT_QOS_DEFAULTcreate_participant()DomainParticipant::set_qos()

系统启动时,默认的 DomainParticipantQos 等价于默认的构造值DomainParticipantQos()。可以随时使用 set_default_participant_qos() DomainParticipantFactory 单例上的成员函数修改默认 DomainParticipantQos。修改默认 DomainParticipantQos 不会影响已经存在的 DomainParticipant 实例。

// Get the current QoS or create a new one from scratch
DomainParticipantQos qos_type1 = DomainParticipantFactory::get_instance()->get_default_participant_qos();

// Modify QoS attributes
// (...)

// Set as the new default TopicQos
if (DomainParticipantFactory::get_instance()->set_default_participant_qos(qos_type1) !=
        ReturnCode_t::RETCODE_OK)
{
    // Error
    return;
}

// Create a DomainParticipant with the new default DomainParticipantQos.
DomainParticipant* participant_with_qos_type1 =
        DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT);
if (nullptr == participant_with_qos_type1)
{
    // Error
    return;
}

// Get the current QoS or create a new one from scratch
DomainParticipantQos qos_type2;

// Modify QoS attributes
// (...)

// Set as the new default TopicQos
if (DomainParticipantFactory::get_instance()->set_default_participant_qos(qos_type2) !=
        ReturnCode_t::RETCODE_OK)
{
    // Error
    return;
}

// Create a Topic with the new default TopicQos.
DomainParticipant* participant_with_qos_type2 =
        DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT);
if (nullptr == participant_with_qos_type2)
{
    // Error
    return;
}

// Resetting the default DomainParticipantQos to the original default constructed values
if (DomainParticipantFactory::get_instance()->set_default_participant_qos(PARTICIPANT_QOS_DEFAULT)
        != ReturnCode_t::RETCODE_OK)
{
    // Error
    return;
}

// The previous instruction is equivalent to the following
if (DomainParticipantFactory::get_instance()->set_default_participant_qos(DomainParticipantQos())
        != ReturnCode_t::RETCODE_OK)
{
    // Error
    return;
}

set_default_participant_qos() 成员函数也接受该值PARTICIPANT_QOS_DEFAULT 作为输入参数。这会将当前默认 DomainParticipantQos 重置为默认构造值 DomainParticipantQos()

// Create a custom DomainParticipantQos
DomainParticipantQos custom_qos;

// Modify QoS attributes
// (...)

// Create a DomainParticipant with a custom DomainParticipantQos

DomainParticipant* participant = DomainParticipantFactory::get_instance()->create_participant(0, custom_qos);
if (nullptr == participant)
{
    // Error
    return;
}

// Set the QoS on the participant to the default
if (participant->set_qos(PARTICIPANT_QOS_DEFAULT) != ReturnCode_t::RETCODE_OK)
{
    // Error
    return;
}

// The previous instruction is equivalent to the following:
if (participant->set_qos(DomainParticipantFactory::get_instance()->get_default_participant_qos())
        != ReturnCode_t::RETCODE_OK)
{
    // Error
    return;
}

该值PARTICIPANT_QOS_DEFAULT具有不同的含义,具体取决于它的使用位置:

create_participant(),DomainParticipant::set_qos()它指的是由返回的默认 DomainParticipantQos get_default_participant_qos()。

set_default_participant_qos()它指的是默认构造 DomainParticipantQos()的.

域参与者监听器

DomainParticipantListener是一个抽象类,定义了将响应DomainParticipant上的状态更改而触发的回调。默认情况下,所有这些回调都是空的并且什么都不做。用户应实现此类的特化,覆盖应用程序所需的回调。未被覆盖的回调将保持其空实现。

DomainParticipantListener 继承自TopicListener、 PublisherListener和SubscriberListener。因此,它有能力对报告给它的任何附属实体的每一种事件做出反应。由于事件总是被通知给可以处理事件的最具体的实体侦听器,因此只有在没有其他实体能够处理事件时才会调用 DomainParticipantListener 从其他侦听器继承的回调,因为它没有附加侦听器,或者因为StatusMask实体上的禁用回调。

此外,DomainParticipantListener 添加了以下回调:

on_participant_discovery(): 在同一个域中发现了一个新的 DomainParticipant,以前已知的 DomainParticipant 已被删除,或者某些 DomainParticipant 已更改其 QoS。

on_subscriber_discovery():在同一个域中发现了一个新的订阅者,一个先前已知的订阅者已被删除,或者某个订阅者已经改变了它的 QoS。

on_publisher_discovery():在同一个域中发现了一个新的Publisher ,以前已知的 Publisher 已被删除,或者某些 Publisher 已更改其 QoS。

on_type_discovery(): 在同一个域中发现了一个新的数据类型。

on_type_dependencies_reply():类型查找客户端收到了对getTypeDependencies()请求的重播。此回调可用于使用getTypes()请求检索新类型,并使用检索到的类型对象创建新的动态类型。

on_type_information_received():TypeInformation已从新发现的 DomainParticipant 收到新消息。

onParticipantAuthentication():通知远程域参与者的身份验证过程的结果(失败或成功)。

class CustomDomainParticipantListener : public DomainParticipantListener
{

public:

    CustomDomainParticipantListener()
        : DomainParticipantListener()
    {
    }

    virtual ~CustomDomainParticipantListener()
    {
    }

    virtual void on_participant_discovery(
            DomainParticipant* /*participant*/,
            eprosima::fastrtps::rtps::ParticipantDiscoveryInfo&& info)
    {
        if (info.status == eprosima::fastrtps::rtps::ParticipantDiscoveryInfo::DISCOVERED_PARTICIPANT)
        {
            std::cout << "New participant discovered" << std::endl;
        }
        else if (info.status == eprosima::fastrtps::rtps::ParticipantDiscoveryInfo::REMOVED_PARTICIPANT ||
                info.status == eprosima::fastrtps::rtps::ParticipantDiscoveryInfo::DROPPED_PARTICIPANT)
        {
            std::cout << "New participant lost" << std::endl;
        }
    }

#if HAVE_SECURITY
    virtual void onParticipantAuthentication(
            DomainParticipant* /*participant*/,
            eprosima::fastrtps::rtps::ParticipantAuthenticationInfo&& info)
    {
        if (info.status == eprosima::fastrtps::rtps::ParticipantAuthenticationInfo::AUTHORIZED_PARTICIPANT)
        {
            std::cout << "A participant was authorized" << std::endl;
        }
        else if (info.status == eprosima::fastrtps::rtps::ParticipantAuthenticationInfo::UNAUTHORIZED_PARTICIPANT)
        {
            std::cout << "A participant failed authorization" << std::endl;
        }
    }

#endif // if HAVE_SECURITY

    virtual void on_subscriber_discovery(
            DomainParticipant* /*participant*/,
            eprosima::fastrtps::rtps::ReaderDiscoveryInfo&& info)
    {
        if (info.status == eprosima::fastrtps::rtps::ReaderDiscoveryInfo::DISCOVERED_READER)
        {
            std::cout << "New subscriber discovered" << std::endl;
        }
        else if (info.status == eprosima::fastrtps::rtps::ReaderDiscoveryInfo::REMOVED_READER)
        {
            std::cout << "New subscriber lost" << std::endl;
        }
    }

    virtual void on_publisher_discovery(
            DomainParticipant* /*participant*/,
            eprosima::fastrtps::rtps::WriterDiscoveryInfo&& info)
    {
        if (info.status == eprosima::fastrtps::rtps::WriterDiscoveryInfo::DISCOVERED_WRITER)
        {
            std::cout << "New publisher discovered" << std::endl;
        }
        else if (info.status == eprosima::fastrtps::rtps::WriterDiscoveryInfo::REMOVED_WRITER)
        {
            std::cout << "New publisher lost" << std::endl;
        }
    }

    virtual void on_type_discovery(
            DomainParticipant* participant,
            const eprosima::fastrtps::rtps::SampleIdentity& request_sample_id,
            const eprosima::fastrtps::string_255& topic,
            const eprosima::fastrtps::types::TypeIdentifier* identifier,
            const eprosima::fastrtps::types::TypeObject* object,
            eprosima::fastrtps::types::DynamicType_ptr dyn_type)
    {
        (void)participant, (void)request_sample_id, (void)topic, (void)identifier, (void)object, (void)dyn_type;
        std::cout << "New data type discovered" << std::endl;

    }

    virtual void on_type_dependencies_reply(
            DomainParticipant* participant,
            const eprosima::fastrtps::rtps::SampleIdentity& request_sample_id,
            const eprosima::fastrtps::types::TypeIdentifierWithSizeSeq& dependencies)
    {
        (void)participant, (void)request_sample_id, (void)dependencies;
        std::cout << "Answer to a request for type dependencies was received" << std::endl;
    }

    virtual void on_type_information_received(
            DomainParticipant* participant,
            const eprosima::fastrtps::string_255 topic_name,
            const eprosima::fastrtps::string_255 type_name,
            const eprosima::fastrtps::types::TypeInformation& type_information)
    {
        (void)participant, (void)topic_name, (void)type_name, (void)type_information;
        std::cout << "New data type information received" << std::endl;
    }

};

域参与者工厂

此类的唯一目的是允许创建和销毁DomainParticipant对象。 DomainParticipantFactory本身没有工厂,是一个单例对象,可以通过类get_instance()上的静态成员函数访问DomainParticipantFactory 。

DomainParticipantFactory 的行为可以使用DomainParticipantFactoryQos上指定的 QoS 值进行修改。由于 DomainParticipantFactory 是一个单例,它的 QoS 只能通过 DomainParticipantFactory::set_qos()成员函数来修改。

DomainParticipantFactory 不接受任何侦听器,因为它不是实体。

DomainParticipantFactoryQos

DomainParticipantFactoryQos 控制 DomainParticipantFactory 的行为。它在内部包含以下QosPolicy对象:
在这里插入图片描述

由于 DomainParticipantFactory 是一个单例,它的 QoS 只能通过 DomainParticipantFactory::set_qos()成员函数来修改。

DomainParticipantFactoryQos qos;

// Setting autoenable_created_entities to true makes the created DomainParticipants
// to be enabled upon creation
qos.entity_factory().autoenable_created_entities = true;
if (DomainParticipantFactory::get_instance()->set_qos(qos) != ReturnCode_t::RETCODE_OK)
{
    // Error
    return;
}

// Create a DomainParticipant with the new DomainParticipantFactoryQos.
// The returned DomainParticipant is already enabled
DomainParticipant* enabled_participant =
        DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT);
if (nullptr == enabled_participant)
{
    // Error
    return;
}

// Setting autoenable_created_entities to false makes the created DomainParticipants
// to be disabled upon creation
qos.entity_factory().autoenable_created_entities = false;
if (DomainParticipantFactory::get_instance()->set_qos(qos) != ReturnCode_t::RETCODE_OK)
{
    // Error
    return;
}

// Create a DomainParticipant with the new DomainParticipantFactoryQos.
// The returned DomainParticipant is disabled and will need to be enabled explicitly
DomainParticipant* disabled_participant =
        DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT);
if (nullptr == disabled_participant)
{
    // Error
    return;
}

从 XML 文件加载配置文件

要基于 XML 配置文件创建实体,必须首先加载包含此类配置文件的文件。

如果配置文件在默认加载的文件之一中进行了描述,它将在初始化时自动可用。否则,load_XML_profiles_file()成员函数可用于加载 XML 中的配置文件。有关 XML 配置文件格式和自动加载的更多信息,请参阅 XML 配置文件部分。

加载后,配置文件的名称可用于根据配置文件规范创建具有 QoS 设置的实体

// Load the XML with the profiles
DomainParticipantFactory::get_instance()->load_XML_profiles_file("profiles.xml");

// Profiles can now be used to create Entities
DomainParticipant* participant_with_profile =
        DomainParticipantFactory::get_instance()->create_participant_with_profile(0, "participant_profile");
if (nullptr == participant_with_profile)
{
    // Error
    return;
}

创建域参与者

DomainParticipant的创建是通过DomainParticipantFactorycreate_participant()单例 上的成员函数 完成的,该函数充当 DomainParticipant 的工厂。

强制性论点是:

标识将DomainId在其中创建 DomainParticipant 的域。

描述DomainParticipant行为的DomainParticipantQos。如果提供TOPIC_QOS_DEFAULT的值为 ,则使用 DomainParticipantQos 的值。

可选参数是:

从DomainParticipantListener派生的侦听器,实现将触发的回调以响应 DomainParticipant 上的事件和状态更改。默认情况下使用空回调。

StatusMask激活或停用触发 DomainParticipantListener 上的单个 回调的A。默认情况下,所有事件都已启用。

create_participant() 如果在操作过程中出现错误,将返回一个空指针,例如,如果提供的 QoS 不兼容或不受支持。建议检查返回值是否为有效指针。

// Create a DomainParticipant with default DomainParticipantQos and no Listener
// The value PARTICIPANT_QOS_DEFAULT is used to denote the default QoS.
DomainParticipant* participant_with_default_attributes =
        DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT);
if (nullptr == participant_with_default_attributes)
{
    // Error
    return;
}

// A custom DomainParticipantQos can be provided to the creation method
DomainParticipantQos custom_qos;

// Modify QoS attributes
// (...)

DomainParticipant* participant_with_custom_qos =
        DomainParticipantFactory::get_instance()->create_participant(0, custom_qos);
if (nullptr == participant_with_custom_qos)
{
    // Error
    return;
}

// Create a DomainParticipant with default QoS and a custom Listener.
// CustomDomainParticipantListener inherits from DomainParticipantListener.
// The value PARTICIPANT_QOS_DEFAULT is used to denote the default QoS.
CustomDomainParticipantListener custom_listener;
DomainParticipant* participant_with_default_qos_and_custom_listener =
        DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT,
                &custom_listener);
if (nullptr == participant_with_default_qos_and_custom_listener)
{
    // Error
    return;
}

基于配置文件的 DomainParticipant 创建

除了使用 DomainParticipantQos 之外,配置文件的名称可用于创建具有 DomainParticipantFactory 单例上的create_participant_with_profile() 成员函数的DomainParticipant。

强制性论点是:

标识将DomainId在其中创建 DomainParticipant 的域。不要使用DomainId高于 200 的值(请参阅创建 DomainParticipant)。

要应用于 DomainParticipant 的配置文件的名称。

可选参数是:

从DomainParticipantListener派生的侦听器,实现将触发的回调以响应 DomainParticipant 上的事件和状态更改。默认情况下使用空回调。

StatusMask激活或停用触发 DomainParticipantListener 上的单个 回调的A。默认情况下,所有事件都已启用。

create_participant_with_profile()如果在操作过程中出现错误,将返回一个空指针,例如,如果提供的 QoS 不兼容或不受支持。建议检查返回值是否为有效指针。

XML 配置文件必须先前已加载。请参阅从 XML 文件加载配置文件。

// First load the XML with the profiles
DomainParticipantFactory::get_instance()->load_XML_profiles_file("profiles.xml");

// Create a DomainParticipant using a profile and no Listener
DomainParticipant* participant_with_profile =
        DomainParticipantFactory::get_instance()->create_participant_with_profile(0, "participant_profile");
if (nullptr == participant_with_profile)
{
    // Error
    return;
}

// Create a DomainParticipant using a profile and a custom Listener.
// CustomDomainParticipantListener inherits from DomainParticipantListener.
CustomDomainParticipantListener custom_listener;
DomainParticipant* participant_with_profile_and_custom_listener =
        DomainParticipantFactory::get_instance()->create_participant_with_profile(0, "participant_profile",
                &custom_listener);
if (nullptr == participant_with_profile_and_custom_listener)
{
    // Error
    return;
}

删除域参与者

可以使用DomainParticipantFactory 单例delete_participant()上的成员函数 删除DomainParticipant。
只有当属于参与者(发布者、订阅者或主题)的所有实体都已被删除时,才能删除 DomainParticipant。否则,该函数将发出错误,并且不会删除 DomainParticipant。这可以通过使用DomainParticipantdelete_contained_entities()的成员函数来 执行。

// Create a DomainParticipant
DomainParticipant* participant =
        DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT);
if (nullptr == participant)
{
    // Error
    return;
}

// Use the DomainParticipant to communicate
// (...)

// Delete entities created by the DomainParticipant
if (participant->delete_contained_entities() != ReturnCode_t::RETCODE_OK)
{
    // DomainParticipant failed to delete the entities it created.
    return;
}

// Delete the DomainParticipant
if (DomainParticipantFactory::get_instance()->delete_participant(participant) != ReturnCode_t::RETCODE_OK)
{
    // Error
    return;
}
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DDS(Data Distribution Service)是一种用于数据传输和通信的中间件协议,它可以在分布式系统中实现高效的数据传输和通信。在Python中,可以使用OpenDDS库来实现DDS服务。 以下是Python实现DDS服务的基本步骤: 1. 下载和安装OpenDDS库,并配置环境变量。 2. 创建IDL文件,定义数据类型和接口。例如: ``` module MyModule { struct MyData { long id; string name; }; interface MyInterface { void sendData(in MyData data); }; }; ``` 3. 使用命令行工具生成Python代码。例如: ``` $ cd <path-to-idl-file> $ $DDS_ROOT/bin/idlpp -l python MyModule.idl ``` 4. 编写Python代码实现接口和数据类型。例如: ```python from mymodule_idl import MyData, MyInterface from OpenDDS import DCPS class MyInterface_i(DCPS.DataWriterRemote): def sendData(self, data): print("Received data: id={}, name={}".format(data.id, data.name)) participant = DCPS.DomainParticipantFactory.get_instance().create_participant(4, OpenDDS.DCPS.DEFAULT_DOMAIN_ID_DEFAULT, OpenDDS.DCPS.TheParticipantFactory.get_instance().get_qos()) topic_qos = OpenDDS.DCPS.TopicQos() participant.get_default_topic_qos(topic_qos) topic = participant.create_topic("MyTopic", "MyModule::MyData", topic_qos) publisher_qos = OpenDDS.DCPS.PublisherQos() participant.get_default_publisher_qos(publisher_qos) publisher = participant.create_publisher(publisher_qos) data_writer_qos = OpenDDS.DCPS.DataWriterQos() publisher.get_default_datawriter_qos(data_writer_qos) data_writer = publisher.create_datawriter(topic, data_writer_qos) my_interface = MyInterface_i() data_writer.set_listener(my_interface, OpenDDS.DCPS.DataWriterListener.NEW_INSTANCE) for i in range(1, 10): data = MyData() data.id = i data.name = "Data{}".format(i) data_writer.write(data, None) ``` 5. 运行Python代码,启动DDS服务。例如: ``` $ python myinterface.py ``` 这样就可以通过DDS协议在Python中实现数据传输和通信了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值