OpenDDS_Linux的环境搭建&开发Demo

目录

一、准备

1.环境

2.下载地址

OpenDDS:Index of /OpenDDS;或者Download

 ACE+TAO:Obtaining ACE, TAO, CIAO and DAnCE

​ 3.解压&加权限

4.配置环境变量

二、编译

1.设置config.h

2.设置Platform_macros.GNU

3.编译

4.运行

​ 三、开发

1. 定义Demo中文件

2.生成Export头文件

 3.定义Demo.mwc

4.编译

5.执行


一、准备

1.环境

Linux:Ubuntu 18.04

2.下载地址

OpenDDS:Index of /OpenDDS;或者Download

 ACE+TAO:Obtaining ACE, TAO, CIAO and DAnCE

 3.解压&加权限

将OpenDDS和ACE解压到同一目录下

并且给这两个文件夹加权限

sudo chmod 777 -R ACE_wrappers/

sudo chmod 777 -R OpenDDS-3.18.1/

4.配置环境变量

ACE_ROOT=/home/ts/Survey/DevOpenDDS/ACE_wrappers
export ACE_ROOT
TAO_ROOT=$ACE_ROOT/TAO
export TAO_ROOT
DDS_ROOT=/home/ts/Survey/DevOpenDDS/OpenDDS-3.18.1
export DDS_ROOT
PATH=$ACE_ROOT/bin:$DDS_ROOT/bin:$PATH
export PATH
LD_LIBRARY_PATH=$ACE_ROOT/lib:$DDS_ROOT/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH

二、编译

1.设置config.h

路径:/home/ts/Survey/DevOpenDDS/ACE_wrappers/ace

内容如下

#include "ace/config-linux.h"

2.设置Platform_macros.GNU

路径:/home/ts/Survey/DevOpenDDS/ACE_wrappers/include/makeinclude

内容如下

include $(ACE_ROOT)/include/makeinclude/platform_linux.GNU

3.编译

编译顺序为:ACE -> TAO -> DDS

3.1 ACE编译

cd $ACE_ROOT
make clean
make

3.2 TAO编译

cd $TAO_ROOT
make clean
make

3.3 DDS编译

cd $DDS_ROOT
./configure
make clean
make

4.运行

cd $DDS_ROOT/example/DCPS/Messenger_Imr
perl ./run_test.pl

出现Test PASSED    成功

 三、开发

1. 定义Demo中文件

 Demo.idl

module DemoIdlModule {
  @topic
  struct DemoTopic1 {
    @key long id;
    long counter;
    string text;
  };
};

Demo.mpc

project(*Idl) : dcps {
  sharedname     = DemoIdl
  dynamicflags   = DEMOIDL_BUILD_DLL
  libout         = .
  requires += tao_orbsvcs
  requires += no_opendds_safety_profile
  after    += Svc_Utils
  includes      += $(TAO_ROOT)/orbsvcs
  idlflags      += -I$(TAO_ROOT)/orbsvcs \
                   -Wb,export_macro=DemoIDL_Export \
                   -Wb,export_include=DemoIDL_Export.h
  dcps_ts_flags += -Wb,export_macro=DemoIDL_Export

  TypeSupport_Files {
    Demo.idl
  }

  IDL_Files {
    Demo.idl
  }

  // We only want the generated files
  Header_Files {
  }

  // We only want the generated files
  Source_Files {
  }
}

project(Publisher) : dcpsexe, dcps_tcp, svc_utils {
  after    += *Idl
  exename   = Publisher
  requires += tao_orbsvcs
  requires += no_opendds_safety_profile

  includes += $(TAO_ROOT)/orbsvcs
  libs     += DemoIdl

  IDL_Files {
  }

  TypeSupport_Files {
  }

  Header_Files {
  }

  Source_Files {
    Publisher.cpp
  }
}

project(Subscriber) : dcpsexe, dcps_tcp {
  after    += *Idl
  exename   = Subscriber
  requires += tao_orbsvcs
  requires += no_opendds_safety_profile

  includes += $(TAO_ROOT)/orbsvcs
  libs     += DemoIdl

  TypeSupport_Files {
  }

  IDL_Files {
  }

  Header_Files {
  }

  Source_Files {
    Subscriber.cpp
    DataReaderListener.cpp
  }

}

DataReaderListener.cpp

// -*- C++ -*-
//
#include "DataReaderListener.h"
#include "DemoTypeSupportC.h"
#include "DemoTypeSupportImpl.h"
#include <dds/DCPS/Service_Participant.h>
#include <ace/streams.h>
 
using namespace DemoIdlModule;
 
DataReaderListener::DataReaderListener()
    : num_reads_(0)
{
}
 
DataReaderListener::~DataReaderListener()
{
}
 
void DataReaderListener::on_data_available(DDS::DataReader_ptr reader)
{
    ++num_reads_;
 
    try {
        DemoTopic1DataReader_var message_dr = DemoTopic1DataReader::_narrow(reader);
        if (CORBA::is_nil(message_dr.in())) {
            cerr << "read: _narrow failed." << endl;
            exit(1);
        }
 
        DemoTopic1 message;
        DDS::SampleInfo si;
        DDS::ReturnCode_t status = message_dr->take_next_sample(message, si);
 
        if (status == DDS::RETCODE_OK) {
            cout << "Message: id    = " << message.id << endl
                << "         DemoTopic1_Counter = " << message.counter << endl
                << "         DemoTopic1_Text = " << message.text << endl;
 
            cout << "SampleInfo.sample_rank = " << si.sample_rank << endl;
        }
        else if (status == DDS::RETCODE_NO_DATA) {
            cerr << "ERROR: reader received DDS::RETCODE_NO_DATA!" << endl;
        }
        else {
            cerr << "ERROR: read Message: Error: " << status << endl;
        }
    }
    catch (CORBA::Exception& e) {
        cerr << "Exception caught in read:" << endl << e << endl;
        exit(1);
    }
}
 
void DataReaderListener::on_requested_deadline_missed(
    DDS::DataReader_ptr,
    const DDS::RequestedDeadlineMissedStatus&)
{
    cerr << "DataReaderListener::on_requested_deadline_missed" << endl;
}
 
void DataReaderListener::on_requested_incompatible_qos(
    DDS::DataReader_ptr,
    const DDS::RequestedIncompatibleQosStatus&)
{
    cerr << "DataReaderListener::on_requested_incompatible_qos" << endl;
}
 
void DataReaderListener::on_liveliness_changed(
    DDS::DataReader_ptr,
    const DDS::LivelinessChangedStatus&)
{
    cerr << "DataReaderListener::on_liveliness_changed" << endl;
}
 
void DataReaderListener::on_subscription_matched(
    DDS::DataReader_ptr,
    const DDS::SubscriptionMatchedStatus&)
{
    cerr << "DataReaderListener::on_subscription_matched" << endl;
}
 
void DataReaderListener::on_sample_rejected(
    DDS::DataReader_ptr,
    const DDS::SampleRejectedStatus&)
{
    cerr << "DataReaderListener::on_sample_rejected" << endl;
}
 
void DataReaderListener::on_sample_lost(
    DDS::DataReader_ptr,
    const DDS::SampleLostStatus&)
{
    cerr << "DataReaderListener::on_sample_lost" << endl;
}
 
void DataReaderListener::on_subscription_disconnected(
    DDS::DataReader_ptr,
    const ::OpenDDS::DCPS::SubscriptionDisconnectedStatus&)
{
    cerr << "DataReaderListener::on_subscription_disconnected" << endl;
}
 
void DataReaderListener::on_subscription_reconnected(
    DDS::DataReader_ptr,
    const ::OpenDDS::DCPS::SubscriptionReconnectedStatus&)
{
    cerr << "DataReaderListener::on_subscription_reconnected" << endl;
}
 
void DataReaderListener::on_subscription_lost(
    DDS::DataReader_ptr,
    const ::OpenDDS::DCPS::SubscriptionLostStatus&)
{
    cerr << "DataReaderListener::on_subscription_lost" << endl;
}
 
void DataReaderListener::on_budget_exceeded(
    DDS::DataReader_ptr,
    const ::OpenDDS::DCPS::BudgetExceededStatus&)
{
    cerr << "DataReaderListener::on_budget_exceeded" << endl;
}

DataReaderListener.h

// -*- C++ -*-
// 数据读者监听者实现
#ifndef DATAREADER_LISTENER_IMPL
#define DATAREADER_LISTENER_IMPL
 
#include <dds/DdsDcpsSubscriptionExtC.h>
#include <dds/DCPS/LocalObject.h>
 
#if !defined (ACE_LACKS_PRAGMA_ONCE)
#pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
 
class DataReaderListener
    : public virtual OpenDDS::DCPS::LocalObject<OpenDDS::DCPS::DataReaderListener>
{
public:
    DataReaderListener();
 
    virtual ~DataReaderListener(void);
 
    virtual void on_requested_deadline_missed(
        DDS::DataReader_ptr reader,
        const DDS::RequestedDeadlineMissedStatus& status);
 
    virtual void on_requested_incompatible_qos(
        DDS::DataReader_ptr reader,
        const DDS::RequestedIncompatibleQosStatus& status);
 
    virtual void on_liveliness_changed(
        DDS::DataReader_ptr reader,
        const DDS::LivelinessChangedStatus& status);
 
    virtual void on_subscription_matched(
        DDS::DataReader_ptr reader,
        const DDS::SubscriptionMatchedStatus& status);
 
    virtual void on_sample_rejected(
        DDS::DataReader_ptr reader,
        const DDS::SampleRejectedStatus& status);
 
    virtual void on_data_available(
        DDS::DataReader_ptr reader);
 
    virtual void on_sample_lost(
        DDS::DataReader_ptr reader,
        const DDS::SampleLostStatus& status);
 
    virtual void on_subscription_disconnected(
        DDS::DataReader_ptr reader,
        const ::OpenDDS::DCPS::SubscriptionDisconnectedStatus& status);
 
    virtual void on_subscription_reconnected(
        DDS::DataReader_ptr reader,
        const ::OpenDDS::DCPS::SubscriptionReconnectedStatus& status);
 
    virtual void on_subscription_lost(
        DDS::DataReader_ptr reader,
        const ::OpenDDS::DCPS::SubscriptionLostStatus& status);
 
    virtual void on_budget_exceeded(
        DDS::DataReader_ptr reader,
        const ::OpenDDS::DCPS::BudgetExceededStatus& status);
 
    long num_reads() const {
        return num_reads_;
    }
 
private:
 
    DDS::DataReader_var reader_;
    long                  num_reads_;
};
 
#endif /* DATAREADER_LISTENER_IMPL  */

Publisher.cpp

#include <dds/DCPS/Service_Participant.h>
#include <dds/DCPS/Marked_Default_Qos.h>
#include <dds/DCPS/PublisherImpl.h>
#include <dds/DCPS/transport/tcp/TcpInst.h>
#include "dds/DCPS/StaticIncludes.h"
 
#include <ace/streams.h>
 
#include "DemoTypeSupportImpl.h"
using namespace DemoIdlModule;
 
 
int ACE_TMAIN(int argc, ACE_TCHAR* argv[]) {
    try {
        // 初始化参与者
        argv[1] = "-DCPSConfigFile";
        argv[2] = "config_Pub.ini";
        argc = 3;
 
        // 1. 初始化参与者
        DDS::DomainParticipantFactory_var dpf =
            TheParticipantFactoryWithArgs(argc, argv);
 
        DDS::DomainParticipant_var participant =
            dpf->create_participant(111,
                PARTICIPANT_QOS_DEFAULT,
                DDS::DomainParticipantListener::_nil(),
                ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
        if (CORBA::is_nil(participant.in())) {
            cerr << "create_participant failed." << endl;
            return 1;
        }
 
        // 2. 注册数据类型
        //这里是Topic而不是Topics,意义不同,体现在idl文件里。
        DemoTopic1TypeSupportImpl* servant = new  DemoTopic1TypeSupportImpl();//这句是要根据XXXXTypeSupportImpl中的前缀与idl文件中的Topic key名对应,在这里即"DemoTopic1"
        OpenDDS::DCPS::LocalObject_var safe_servant = servant;
 
        if (DDS::RETCODE_OK != servant->register_type(participant.in(), "")) {
            cerr << "register_type failed." << endl;
            exit(1);
        }
 
        // 3. 创建主题,这部分基本不用改
        CORBA::String_var type_name = servant->get_type_name();
 
        DDS::TopicQos topic_qos;
        participant->get_default_topic_qos(topic_qos);
        DDS::Topic_var topic =
            participant->create_topic("Movie Discussion List",
                type_name.in(),
                topic_qos,
                DDS::TopicListener::_nil(),
                ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
        if (CORBA::is_nil(topic.in())) {
            cerr << "create_topic failed." << endl;
            exit(1);
        }
 
        // 4. 创建公布者,这部分基本不用改
        DDS::Publisher_var pub =
            participant->create_publisher(PUBLISHER_QOS_DEFAULT,
                DDS::PublisherListener::_nil(),
                ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
        if (CORBA::is_nil(pub.in())) {
            cerr << "create_publisher failed." << endl;
            exit(1);
        }
 
        // 5. 创建数据写者
        DDS::DataWriterQos dw_qos;
        pub->get_default_datawriter_qos(dw_qos);
        DDS::DataWriter_var dw =
            pub->create_datawriter(topic.in(),
                dw_qos,
                DDS::DataWriterListener::_nil(),
                ::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
        if (CORBA::is_nil(dw.in())) {
            cerr << "create_datawriter failed." << endl;
            exit(1);
        }
        DemoTopic1DataWriter_var message_dw //这句是要根据XXXXDataWriter_var,XXXXDataWriter中的前缀与idl文件中的Topic key名对应,在这里即"DemoTopic1"
            = DemoTopic1DataWriter::_narrow(dw.in());
 
        //
        // Get default Publisher QoS from a DomainParticipant:
        DDS::PublisherQos pub_qos;
        DDS::ReturnCode_t ret;
        ret = participant->get_default_publisher_qos(pub_qos);
 
        if (DDS::RETCODE_OK != ret) {
            std::cerr << "Could not get default publisher QoS" << std::endl;
        }
 
        // Get default Subscriber QoS from a DomainParticipant:
        DDS::SubscriberQos sub_qos;
        ret = participant->get_default_subscriber_qos(sub_qos);
        if (DDS::RETCODE_OK != ret) {
            std::cerr << "Could not get default subscriber QoS" << std::endl;
        }
 
        // Get default Topic QoS from a DomainParticipant:
        DDS::TopicQos topic_qos2;
        ret = participant->get_default_topic_qos(topic_qos2);
        if (DDS::RETCODE_OK != ret) {
            std::cerr << "Could not get default topic QoS" << std::endl;
        }
 
        // Get default DomainParticipant QoS from a DomainParticipantFactory:
        DDS::DomainParticipantQos dp_qos;
        ret = dpf->get_default_participant_qos(dp_qos);
        if (DDS::RETCODE_OK != ret) {
            std::cerr << "Could not get default participant QoS" << std::endl;
        }
 
        // Get default DataWriter QoS from a Publisher:
        DDS::DataWriterQos dw_qos2;
        ret = pub->get_default_datawriter_qos(dw_qos2);
        if (DDS::RETCODE_OK != ret) {
            std::cerr << "Could not get default data writer QoS" << std::endl;
        }
        
 
        // 6. 公布数据
        DemoTopic1 message;//这句是要根据idl文件中的Topic key名对应,在这里即"DemoTopic1"
        message.id = 99;
        ::DDS::InstanceHandle_t handle = message_dw->register_instance(message);
        message.counter = 0;
 
        char tMsg[50] = { 0 };
        while (1)
        {
            message.counter++;
            memset(tMsg, 0, 50);
            sprintf(tMsg, "Msg Counter : %d", message.counter);
            message.text =  ::TAO::String_Manager(tMsg);
            message_dw->write(message, handle);
            ACE_OS::sleep(1);
            cout << "..." << endl;
        }
        
 
        // 7. 实体清理
        participant->delete_contained_entities();
        dpf->delete_participant(participant);
        TheServiceParticipant->shutdown();
    }
    catch (CORBA::Exception& e)
    {
        cerr << "PUB: Exception caught in main.cpp:" << endl
            << e << endl;
        exit(1);
    }
 
    return 0;
}

Subscriber.cpp

#include "DemoTypeSupportImpl.h"
#include <dds/DCPS/Service_Participant.h>
#include <dds/DCPS/Marked_Default_Qos.h>
#include <dds/DCPS/PublisherImpl.h>
#include <dds/DCPS/transport/tcp/TcpInst.h>
 
#include "dds/DCPS/StaticIncludes.h"
#include <ace/streams.h>
 
#include "DataReaderListener.h"
 
using namespace DemoIdlModule;
 
 
int ACE_TMAIN(int argc, ACE_TCHAR* argv[]) {
	try
	{
		// 初始化参与者
		argv[1] = "-DCPSConfigFile";
		argv[2] = "config_Sub.ini";
		argc = 3;
 
		// 1. 初始化参与者
		DDS::DomainParticipantFactory_var dpf =
			TheParticipantFactoryWithArgs(argc, argv);
 
		DDS::DomainParticipant_var participant =
			dpf->create_participant(111,
				PARTICIPANT_QOS_DEFAULT,
				DDS::DomainParticipantListener::_nil(),
				::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
		if (CORBA::is_nil(participant.in())) {
			cerr << "create_participant failed." << endl;
			return 1;
		}
 
		// 2. 注册数据类型并创建主题
		DemoTopic1TypeSupportImpl* servant = new	DemoTopic1TypeSupportImpl();
		OpenDDS::DCPS::LocalObject_var safe_servant = servant;
 
		if (DDS::RETCODE_OK != servant->register_type(participant.in(), "")) {
			cerr << "register_type failed." << endl;
			exit(1);
		}
 
		CORBA::String_var type_name = servant->get_type_name();
 
		DDS::TopicQos topic_qos;
		participant->get_default_topic_qos(topic_qos);
		DDS::Topic_var topic =
			participant->create_topic("Movie Discussion List",
				type_name.in(),
				topic_qos,
				DDS::TopicListener::_nil(),
				::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
		if (CORBA::is_nil(topic.in())) {
			cerr << "create_topic failed." << endl;
			exit(1);
		}
 
		// 3. 创建订阅者
		DDS::Subscriber_var sub =
			participant->create_subscriber(SUBSCRIBER_QOS_DEFAULT,
				DDS::SubscriberListener::_nil(),
				::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
		if (CORBA::is_nil(sub.in())) {
			cerr << "Failed to create_subscriber." << endl;
			exit(1);
		}
 
		// 4. 创建监听者
		DDS::DataReaderListener_var listener(new DataReaderListener);
		DataReaderListener* listener_servant =
			dynamic_cast<DataReaderListener*>(listener.in());
 
		if (CORBA::is_nil(listener.in())) {
			cerr << "listener is nil." << endl;
			exit(1);
		}
 
		if (!listener_servant) {
			ACE_ERROR_RETURN((LM_ERROR,
				ACE_TEXT("%N:%l main()")
				ACE_TEXT(" ERROR: listener_servant is nil (dynamic_cast failed)!\n")), -1);
		}
 
		// 5. 创建数据读者
		DDS::DataReaderQos dr_qos;
		sub->get_default_datareader_qos(dr_qos);
		DDS::DataReader_var dr = sub->create_datareader(topic.in(),
			dr_qos,
			listener.in(),
			::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
		if (CORBA::is_nil(dr.in())) {
			cerr << "create_datareader failed." << endl;
			exit(1);
		}
 
		//
		// Get default Publisher QoS from a DomainParticipant:
		DDS::PublisherQos pub_qos;
		DDS::ReturnCode_t ret;
		ret = participant->get_default_publisher_qos(pub_qos);
 
		if (DDS::RETCODE_OK != ret) {
			std::cerr << "Could not get default publisher QoS" << std::endl;
		}
 
		// Get default Subscriber QoS from a DomainParticipant:
		DDS::SubscriberQos sub_qos;
		ret = participant->get_default_subscriber_qos(sub_qos);
		if (DDS::RETCODE_OK != ret) {
			std::cerr << "Could not get default subscriber QoS" << std::endl;
		}
 
		// Get default Topic QoS from a DomainParticipant:
		DDS::TopicQos topic_qos2;
		ret = participant->get_default_topic_qos(topic_qos2);
		if (DDS::RETCODE_OK != ret) {
			std::cerr << "Could not get default topic QoS" << std::endl;
		}
 
		// Get default DomainParticipant QoS from a DomainParticipantFactory:
		DDS::DomainParticipantQos dp_qos;
		ret = dpf->get_default_participant_qos(dp_qos);
		if (DDS::RETCODE_OK != ret) {
			std::cerr << "Could not get default participant QoS" << std::endl;
		}
 
		// Get default DataReader QoS from a Subscriber:
		DDS::DataReaderQos dr_qos2;
		ret = sub->get_default_datareader_qos(dr_qos2);
		if (DDS::RETCODE_OK != ret) {
			std::cerr << "Could not get default data reader QoS" << std::endl;
		}
		
 
		while (1) {
			ACE_OS::sleep(1);
		}
 
		// 6. 清理与OpenDDS相关联的资源
		participant->delete_contained_entities();
		dpf->delete_participant(participant);
		TheServiceParticipant->shutdown();
	}
	catch (CORBA::Exception& e)
	{
		cerr << "PUB: Exception caught in main.cpp:" << endl
			<< e << endl;
		exit(1);
	}
 
	return 0;
}

config_Pub.ini&config_Sub.ini

[common]
DCPSGlobalTransportConfig=$file
DCPSDefaultDiscovery=DEFAULT_RTPS
[transport/the_rtps_transport]
transport_type=rtps_udp

2.生成Export头文件

perl $ACE_ROOT/bin/generate_export_file.pl DemoIDL > DemoIDL_Export.h

 3.定义Demo.mwc

workspace {
  // the -relative and -include cmdlines make it so this workspace
  // does not have to be in the $DDS_ROOT directory tree.
 
  // tell MPC to substitute our DDS_ROOT environment variables for relative paths
  cmdline += -relative DDS_ROOT=$DDS_ROOT
 
  // tell the projects where to find the DDS base projects (*.mpb)
  cmdline += -include $DDS_ROOT/MPC/config
 
}

4.编译

1. 生成Makefile

$ACE_ROOT/bin/mwc.pl -type make

2. make编译 

5.执行

./Publisher

./Subscriber

参考:【原创】OpenDDS笔记(二) Linux环境下的环境搭建_jam12315的专栏-CSDN博客

【原创】OpenDDS笔记(一) Windows环境下的开发实例_jam12315的专栏-CSDN博客_opendds开发实例

【原创】OpenDDS笔记(三) Linux环境下的开发实例_jam12315的专栏-CSDN博客

  • 2
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值