DDS Programming
using
IDL to C++11
Overview
This tutorial shows how the famous DDS shapes
example can be implemented using the IDL to C++11
language mapping
It assumes basic understanding of IDL and DDS
For more information take a look at our website
www.remedy.nl
Copyright © Remedy IT2
Problems with IDL to C++
The IDL to C++ language mapping is from the 90’s
IDL to C++ could not depend on various C++
features as
• C++ namespace
• C++ exceptions
• Standard Template Library
As a result
• Mapping is hard to use correctly
• Uses its own constructs for everything
Copyright © Remedy IT3
Why a new language
mapping?
IDL to C++ language mapping is impossible to
change because
• Multiple implementations are on the market (open
source and commercial)
• A huge amount of applications have been developed
An updated IDL to C++ language mapping would
force all vendors and users to update their products
The standardization of a new C++ revision in 2011
(ISO/IEC 14882:2011, called C++11) gives the
opportunity to define a new language mapping
• C++11 features are not backward compatible with
C++03 or C++99
• A new C++11 mapping leaves the existing mapping
intact Copyright © Remedy IT4
Goals
Simplify mapping for C++
Make use of the new C++11 features to
• Reduce amount of application code
• Reduce amount of possible errors made
• Gain runtime performance
• Speedup development and testing
Faster time to market
Reduced costs
Reduced training time
Copyright © Remedy IT5
OMG Specification
IDL to C++11 is now a formal OMG standard
IDL to C++11 v1.2 available from the OMG website
as formal/2015-08-01
Revision Task Force (RTF) is active to work on
issues reported
Copyright © Remedy IT6
More information IDL to C++11
For background, details, tutorials, and examples see
the following websites
• http://taox11.remedy.nl
• http://osportal.remedy.nl
• http://www.orbzone.org
Copyright © Remedy IT7
Shapes
Copyright © Remedy IT8
IDL Topic Type
In order to exchange data we define in IDL a DDS
Topic Type
Based on the IDL Topic Type the following will be
generated
• C++11 type representation
• C++11 type specific DDS API
Copyright © Remedy IT9
ShapeType
IDL definition
struct ShapeType {
string color; //@key
long x;
long y;
long shapesize;
};
Copyright © Remedy IT10
DDS::traits<>
For each IDL Topic Type a set of DDS traits will be
generated
The DDS traits enable access to all implied DDS
entities
Together with the IDL::traits<> we can easily write
C++11 applications that use DDS and have access to
the meta type information from IDL
Copyright © Remedy IT11
DDS::traits<> overview
The following DDS reference traits are used in our
tutorial
A reference behaves like a std::shared_ptr and
for each type also a weak_ref_type is available
Copyright © Remedy IT12
Reference trait Meaning
domainparticipant_ref_type Reference to the DDS DomainParticipant
topic_ref_type Reference to the DDS Topic
publisher_ref_type Reference to the DDS Publisher
datawriter_ref_type Reference to the DDS DataWriter
typed_datawriter_ref_type Reference to the DDS Topic Type DataWriter
subscriber_ref_type Reference to the DDS Subscriber
datareader_ref_type Reference to the DDS DataReader
typed_datareader_ref_type Reference to the DDS Topic Type DataReader
Sender implementation (1)
// Create all DDS entities, if something fails we just return
DDS::ReturnCode_t retcode {DDS::RETCODE_OK};
// Create a domain participant for domain 0 with default QoS
DDS::traits<ShapeType>::domainparticipant_ref_type domain_participant =
DDS::traits<DDS::DomainParticipantFactory>::get_instance ()->create_participant (
0, DDS::PARTICIPANT_QOS_DEFAULT, nullptr, 0);
if (retcode != DDS::RETCODE_OK) return;
// Create a topic with default QoS
DDS::traits<ShapeType>::topic_ref_type topic = domain_participant->create_topic (
"Square", DDS::traits<ShapeType>::get_type_name (), DDS::TOPIC_QOS_DEFAULT, nullptr, 0);
// Create a publisher with default QoS
DDS::traits<ShapeType>::publisher_ref_type publisher =
domain_participant->create_publisher (DDS::PUBLISHER_QOS_DEFAULT, nullptr, 0);
// When we have a publisher and topic we create a datawriter with default QoS
if (publisher && topic) {
DDS::traits<ShapeType>::datawriter_ref_type dw =
publisher->create_datawriter (topic, DDS::DATAWRITER_QOS_DEFAULT, nullptr, 0);
// Narrow the base datawriter to a topic type specific datawriter
DDS::traits<ShapeType>::typed_datawriter_ref_type shape_dw =
DDS::traits<ShapeType>::narrow (dw);
}
Copyright © Remedy IT13
Sender implementation (2)
// When we have a topic type specific datawriter we register an instance to DDS and write data
if (shape_dw) {
ShapeType square {"GREEN", 10, 10, 25};
DDS::InstanceHandle_t instance_handle = shape_dw->register_instance (square);
// Write 100 samples
for (uint32_t i = 0; i < 100; ++i) {
shape_dw->write (square, instance_handle);
std::cout << "Written sample " << square << std::endl;
++square.x(); ++square.y();
std::chrono::milliseconds sleep_time (2000);
std::this_thread::sleep_for (sleep_time);
}
std::cout << std::endl << "Written 100 samples. Last sample: " << square << std::endl;
// Unregister the instance from DDS
shape_dw->unregister_instance (square, instance_handle);
}
Copyright © Remedy IT14
Receiver implementation (1)
// DDS Listener implementation that receives the samples and prints them on the console
class ShapeTypeListener final : public DDS::traits<ShapeType>::datareaderlistener_type {
public:
void ShapeTypeListener::on_data_available (DDS::traits<ShapeType>::datareader_ref_type the_reader) {
DDS::traits<ShapeType>::typed_datareader_ref_type rd =
DDS::traits<ShapeType>::narrow (the_reader);
ShapeType shape;
DDS::SampleInfo info;
for(;;) {
DDS::ReturnCode_t retcode = rd->take_next_sample(shape, info);
if (retcode == DDS::RETCODE_NO_DATA) {
/* No more samples */
break;
} else if (retcode != DDS::RETCODE_OK) {
std::cerr << "Unable to take data from data reader, error “ << retcode << std::endl;
return;
} else if (info.valid_data ()) {
std::cout << "Received <" << ++received_ << ">: " << shape << std::endl;
}
}
// Left other operations out of this class for simplicity
}
Copyright © Remedy IT15
Receiver implementation (2)
// Code that is placed in main
// Create all DDS entities, if something fails we just return
DDS::ReturnCode_t retcode {DDS::RETCODE_OK};
DDS::traits<ShapeType>::domainparticipant_ref_type domain_participant =
DDS::traits< DDS::DomainParticipantFactory >::get_instance ()->create_participant (
0, DDS::PARTICIPANT_QOS_DEFAULT, nullptr, 0);
retcode = DDS::traits<ShapeType>::register_type (domain_participant, "ShapeType");
if (retcode != DDS::RETCODE_OK) return 1;
DDS::traits<ShapeType>::topic_ref_type topic = domain_participant->create_topic (
"Square", DDS::traits<ShapeType>::get_type_name (), DDS::TOPIC_QOS_DEFAULT, nullptr, 0);
DDS::traits<ShapeType>::subscriber_ref_type subscriber =
domain_participant->create_subscriber (DDS::SUBSCRIBER_QOS_DEFAULT, nullptr, 0);
if (topic && subscriber) {
DDS::traits<ShapeType>::datareaderlistener_ref_type listener =
DDS::make_reference<ShapeTypeListener>();
// Create datareader with an instance of the listener
subscriber->create_datareader (topic, DDS::DATAREADER_QOS_DEFAULT, listener,
DDS::DATA_AVAILABLE_STATUS);
// Run the main thread in a loop, give control to a framework, ..
// DDS will do a callback on its own thread
Copyright © Remedy IT16
Contact
Copyright © Remedy IT17
Remedy IT
Postbus 81
6930 AB Westervoort
The Netherlands
tel.: +31(0)88 – 053 0000
e-mail: sales@remedy.nl
website: www.remedy.nl
Twitter: @RemedyIT
Slideshare: RemedyIT
Subscribe to our mailing list

DDS Programming with IDL to C++11 tutorial

  • 1.
  • 2.
    Overview This tutorial showshow the famous DDS shapes example can be implemented using the IDL to C++11 language mapping It assumes basic understanding of IDL and DDS For more information take a look at our website www.remedy.nl Copyright © Remedy IT2
  • 3.
    Problems with IDLto C++ The IDL to C++ language mapping is from the 90’s IDL to C++ could not depend on various C++ features as • C++ namespace • C++ exceptions • Standard Template Library As a result • Mapping is hard to use correctly • Uses its own constructs for everything Copyright © Remedy IT3
  • 4.
    Why a newlanguage mapping? IDL to C++ language mapping is impossible to change because • Multiple implementations are on the market (open source and commercial) • A huge amount of applications have been developed An updated IDL to C++ language mapping would force all vendors and users to update their products The standardization of a new C++ revision in 2011 (ISO/IEC 14882:2011, called C++11) gives the opportunity to define a new language mapping • C++11 features are not backward compatible with C++03 or C++99 • A new C++11 mapping leaves the existing mapping intact Copyright © Remedy IT4
  • 5.
    Goals Simplify mapping forC++ Make use of the new C++11 features to • Reduce amount of application code • Reduce amount of possible errors made • Gain runtime performance • Speedup development and testing Faster time to market Reduced costs Reduced training time Copyright © Remedy IT5
  • 6.
    OMG Specification IDL toC++11 is now a formal OMG standard IDL to C++11 v1.2 available from the OMG website as formal/2015-08-01 Revision Task Force (RTF) is active to work on issues reported Copyright © Remedy IT6
  • 7.
    More information IDLto C++11 For background, details, tutorials, and examples see the following websites • http://taox11.remedy.nl • http://osportal.remedy.nl • http://www.orbzone.org Copyright © Remedy IT7
  • 8.
  • 9.
    IDL Topic Type Inorder to exchange data we define in IDL a DDS Topic Type Based on the IDL Topic Type the following will be generated • C++11 type representation • C++11 type specific DDS API Copyright © Remedy IT9
  • 10.
    ShapeType IDL definition struct ShapeType{ string color; //@key long x; long y; long shapesize; }; Copyright © Remedy IT10
  • 11.
    DDS::traits<> For each IDLTopic Type a set of DDS traits will be generated The DDS traits enable access to all implied DDS entities Together with the IDL::traits<> we can easily write C++11 applications that use DDS and have access to the meta type information from IDL Copyright © Remedy IT11
  • 12.
    DDS::traits<> overview The followingDDS reference traits are used in our tutorial A reference behaves like a std::shared_ptr and for each type also a weak_ref_type is available Copyright © Remedy IT12 Reference trait Meaning domainparticipant_ref_type Reference to the DDS DomainParticipant topic_ref_type Reference to the DDS Topic publisher_ref_type Reference to the DDS Publisher datawriter_ref_type Reference to the DDS DataWriter typed_datawriter_ref_type Reference to the DDS Topic Type DataWriter subscriber_ref_type Reference to the DDS Subscriber datareader_ref_type Reference to the DDS DataReader typed_datareader_ref_type Reference to the DDS Topic Type DataReader
  • 13.
    Sender implementation (1) //Create all DDS entities, if something fails we just return DDS::ReturnCode_t retcode {DDS::RETCODE_OK}; // Create a domain participant for domain 0 with default QoS DDS::traits<ShapeType>::domainparticipant_ref_type domain_participant = DDS::traits<DDS::DomainParticipantFactory>::get_instance ()->create_participant ( 0, DDS::PARTICIPANT_QOS_DEFAULT, nullptr, 0); if (retcode != DDS::RETCODE_OK) return; // Create a topic with default QoS DDS::traits<ShapeType>::topic_ref_type topic = domain_participant->create_topic ( "Square", DDS::traits<ShapeType>::get_type_name (), DDS::TOPIC_QOS_DEFAULT, nullptr, 0); // Create a publisher with default QoS DDS::traits<ShapeType>::publisher_ref_type publisher = domain_participant->create_publisher (DDS::PUBLISHER_QOS_DEFAULT, nullptr, 0); // When we have a publisher and topic we create a datawriter with default QoS if (publisher && topic) { DDS::traits<ShapeType>::datawriter_ref_type dw = publisher->create_datawriter (topic, DDS::DATAWRITER_QOS_DEFAULT, nullptr, 0); // Narrow the base datawriter to a topic type specific datawriter DDS::traits<ShapeType>::typed_datawriter_ref_type shape_dw = DDS::traits<ShapeType>::narrow (dw); } Copyright © Remedy IT13
  • 14.
    Sender implementation (2) //When we have a topic type specific datawriter we register an instance to DDS and write data if (shape_dw) { ShapeType square {"GREEN", 10, 10, 25}; DDS::InstanceHandle_t instance_handle = shape_dw->register_instance (square); // Write 100 samples for (uint32_t i = 0; i < 100; ++i) { shape_dw->write (square, instance_handle); std::cout << "Written sample " << square << std::endl; ++square.x(); ++square.y(); std::chrono::milliseconds sleep_time (2000); std::this_thread::sleep_for (sleep_time); } std::cout << std::endl << "Written 100 samples. Last sample: " << square << std::endl; // Unregister the instance from DDS shape_dw->unregister_instance (square, instance_handle); } Copyright © Remedy IT14
  • 15.
    Receiver implementation (1) //DDS Listener implementation that receives the samples and prints them on the console class ShapeTypeListener final : public DDS::traits<ShapeType>::datareaderlistener_type { public: void ShapeTypeListener::on_data_available (DDS::traits<ShapeType>::datareader_ref_type the_reader) { DDS::traits<ShapeType>::typed_datareader_ref_type rd = DDS::traits<ShapeType>::narrow (the_reader); ShapeType shape; DDS::SampleInfo info; for(;;) { DDS::ReturnCode_t retcode = rd->take_next_sample(shape, info); if (retcode == DDS::RETCODE_NO_DATA) { /* No more samples */ break; } else if (retcode != DDS::RETCODE_OK) { std::cerr << "Unable to take data from data reader, error “ << retcode << std::endl; return; } else if (info.valid_data ()) { std::cout << "Received <" << ++received_ << ">: " << shape << std::endl; } } // Left other operations out of this class for simplicity } Copyright © Remedy IT15
  • 16.
    Receiver implementation (2) //Code that is placed in main // Create all DDS entities, if something fails we just return DDS::ReturnCode_t retcode {DDS::RETCODE_OK}; DDS::traits<ShapeType>::domainparticipant_ref_type domain_participant = DDS::traits< DDS::DomainParticipantFactory >::get_instance ()->create_participant ( 0, DDS::PARTICIPANT_QOS_DEFAULT, nullptr, 0); retcode = DDS::traits<ShapeType>::register_type (domain_participant, "ShapeType"); if (retcode != DDS::RETCODE_OK) return 1; DDS::traits<ShapeType>::topic_ref_type topic = domain_participant->create_topic ( "Square", DDS::traits<ShapeType>::get_type_name (), DDS::TOPIC_QOS_DEFAULT, nullptr, 0); DDS::traits<ShapeType>::subscriber_ref_type subscriber = domain_participant->create_subscriber (DDS::SUBSCRIBER_QOS_DEFAULT, nullptr, 0); if (topic && subscriber) { DDS::traits<ShapeType>::datareaderlistener_ref_type listener = DDS::make_reference<ShapeTypeListener>(); // Create datareader with an instance of the listener subscriber->create_datareader (topic, DDS::DATAREADER_QOS_DEFAULT, listener, DDS::DATA_AVAILABLE_STATUS); // Run the main thread in a loop, give control to a framework, .. // DDS will do a callback on its own thread Copyright © Remedy IT16
  • 17.
    Contact Copyright © RemedyIT17 Remedy IT Postbus 81 6930 AB Westervoort The Netherlands tel.: +31(0)88 – 053 0000 e-mail: sales@remedy.nl website: www.remedy.nl Twitter: @RemedyIT Slideshare: RemedyIT Subscribe to our mailing list