Data Modeling#
Introduction#
What you’ll learn
In this module, you’ll get an introduction to data modeling for data-centric publish-subscribe.
You will do the following:
Define types to model state, events, and periodic information
Generate an example application for these types
Define the quality of service (QoS) for each data flow
You will use System Designer, a graphical tool to define data types and configuration. For reference, snippets in some text formats (IDL and XML) are also provided.
In the Publish-Subscribe module, you created one data type and simple publisher/subscriber applications to demonstrate the publish-subscribe model. In this module, you’ll use System Designer, instead of IDL, to create multiple data types. (System Designer can do much more than this, which you’ll learn in the Application Design module.)
How to complete this module#
To complete this module, you’ll need the following:
20-30 minutes
A Connext installation (full installation).
System Designer (included in the installation).
1. Define the data types#
You’ll model a simple system to track vehicles (position and route) and monitor some metrics, such as fuel level. To start, you’ll define the following types:
VehicleTransit
to identify the vehicle and track it.VehicleMetrics
to monitor periodic updates of the vehicle metrics.
Each vehicle will be a unique object in the system. You’ll use the Vehicle Identification Number (VIN) as a key to identify each vehicle.
Start System Designer from RTI Launcher.
Create a new project by clicking Create New...
. Call the project VehicleModeling
.
When the project opens, click the hamburger icon to open the View menu, then select the Types view. Right-click Types to open the context menu.
From the context menu, add a constant and a type alias (typedef
).
Configure each item as pictured below.
const uint8 VIN_LENGTH = 17;
typedef string<VIN_LENGTH> VIN;
<const name="VIN_LENGTH" type="uint8" value="17"/>
<typedef name="VIN" type="string" stringMaxLength="VIN_LENGTH"/>
So far, you’ve defined:
The constant
VIN_LENGTH
, with a value of 17.The type alias
VIN
, a string with a maximum length ofVIN_LENGTH
characters.
Next, you will define a VehicleTransit
type to model the state of a vehicle.
The publisher applications can publish updates when the state changes, and the
subscriber applications can react to these events.
Define two structs as pictured below. The first is a simple struct to represent a coordinate; the second is the main struct to represent the state of a vehicle.
These structs are currently empty—you need to add fields to them.
Right-click each struct and select Add Member
. Define the
structures as follows:
@nested @final struct Coord { // WSG84 coordinate used by GPS
double lat; // +north, -south
double lon; // +west , -east
};
const string VehicleTransitTopic = "VehicleTransit";
@appendable struct VehicleTransit { // State, Event
@key VIN vehicle_vin;
Coord current_position;
@optional sequence<Coord> current_route; // 'no route' == standby
};
<struct name="Coord" extensibility="final" nested="true">
<member name="lat" type="float64"/>
<member name="lon" type="float64"/>
</struct>
<const name="VehicleTransitTopic" type="string" value=""VehicleTransit""/>
<struct name="VehicleTransit" extensibility="appendable">
<member name="vehicle_vin" type="nonBasic" nonBasicTypeName="VIN" key="true"/>
<member name="current_position" type="nonBasic" nonBasicTypeName="Coord"/>
<member name="current_route" type="nonBasic" nonBasicTypeName="Coord" sequenceMaxLength="-1" optional="true"/>
</struct>
VehicleTransit
is a struct
type with three fields:
vehicle_vin
: identifies an instance of the type, and is therefore a@key
field.current_position
: vehicle’s current position, represented by aCoord
type.current_route
: sequence (a collection) of coordinates. It is@optional
, indicating that each update may or may not include a route.
You’ve also specified an extensibility for each type:
Coord
is a@final
type, meaning it cannot be extended.VehicleTransit
is an@appendable
type (this is the default), which allows applications to add new fields in the future without breaking compatibility.
Type extensibility allows applications to communicate using the same Topic with different, compatible types.
The @nested
annotation is optional and indicates that the Coord
type is
not intended to be used as a Topic by itself, only as part of another type.
Finally, to provide periodic information about our vehicle (fuel levels, in this
example) define a VehicleMetrics
type:
typedef @range(min=0.0, max=100.0) double Percentage;
const string VehicleMetricsTopic = "VehicleMetrics";
@appendable struct VehicleMetrics { // Periodic
@key VIN vehicle_vin;
Percentage fuel_level;
};
<typedef name="Percentage" type="float64" min="0.0" max="100.0"/>
<const name="VehicleMetricsTopic" type="string" value=""VehicleMetrics""/>
<struct name="VehicleMetrics" extensibility="appendable">
<member name="vehicle_vin" type="nonBasic" nonBasicTypeName="VIN" key="true"/>
<member name="fuel_level" type="nonBasic" nonBasicTypeName="Percentage"/>
</struct>
VehicleMetrics
identifies instances using the same key field (vehicle_vin
)
as used for VehicleTransit
. This means that the two different
Topics may refer to the same vehicle.
In both cases, you’ve defined constants with the Topic names, which can be used by the applications to create the Topics.
In summary, the full data types you’ve defined are as follows:
const uint8 VIN_LENGTH = 17;
typedef string<VIN_LENGTH> VIN;
@nested @final struct Coord {
double lat;
double lon;
};
const string VehicleTransitTopic = "VehicleTransit";
@appendable struct VehicleTransit {
@key VIN vehicle_vin;
Coord current_position;
@optional sequence<Coord> current_route;
};
typedef @range(min=0.0, max=100.0) double Percentage;
const string VehicleMetricsTopic = "VehicleMetrics";
@appendable struct VehicleMetrics {
@key VIN vehicle_vin;
Percentage fuel_level;
};
<?xml version="1.0" encoding="UTF-8"?>
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://community.rti.com/schema/current/rti_dds_profiles.xsd">
<types>
<const name="VIN_LENGTH" type="uint8" value="17"/>
<typedef name="VIN" type="string" stringMaxLength="VIN_LENGTH"/>
<struct name="Coord" extensibility="final" nested="true">
<member name="lat" type="float64"/>
<member name="lon" type="float64"/>
</struct>
<const name="VehicleTransitTopic" type="string" value=""VehicleTransit""/>
<struct name="VehicleTransit" extensibility="appendable">
<member name="vehicle_vin" type="nonBasic" nonBasicTypeName="VIN" key="true"/>
<member name="current_position" type="nonBasic" nonBasicTypeName="Coord"/>
<member name="current_route" type="nonBasic" nonBasicTypeName="Coord" sequenceMaxLength="-1" optional="true"/>
</struct>
<typedef name="Percentage" type="float64" min="0.0" max="100.0"/>
<const name="VehicleMetricsTopic" type="string" value=""VehicleMetrics""/>
<struct name="VehicleMetrics" extensibility="appendable">
<member name="vehicle_vin" type="nonBasic" nonBasicTypeName="VIN" key="true"/>
<member name="fuel_level" type="nonBasic" nonBasicTypeName="Percentage"/>
</struct>
</types>
</dds>
2. Generate example applications#
Now that you’ve defined types, use Code Generator (rtiddsgen) to generate simple example applications. The generated application allows you to validate your types and get started writing application code to publish and subscribe to Topics defined by these types.
Run the following command to generate the Python example:
$ rtiddsgen -language python -example universal VehicleModeling.xml
-example
will generate three different things:
A set of files for your data types.
An example publisher application, subscriber application, and QoS configuration for these.
A set of files to build and run these example applications.
To generate the build files for the C++ example, specify a target platform. For example:
Linux:
x64Linux4gcc7.3.0
,armv8Linux4gcc7.3.0
Windows:
x64Win64VS2017
macOS:
x64Darwin20clang12.0
,arm64Darwin20clang12.0
$ rtiddsgen -language c++11 -example x64Linux4gcc7.3.0 VehicleModeling.xml
-example
will generate three different things:
A set of files for your data types.
An example publisher application, subscriber application, and QoS configuration for these.
A set of files to build and run these example applications.
Once the code is generated, build the example applications generated by rtiddsgen for your platform.
Build the applications using the makefile_VehicleModeling_<platform>
file.
For example:
$ make -f makefile_VehicleModeling_x64Linux4gcc7.3.0
Open VehicleModeling-<platform>.sln
in Visual Studio and
compile the project.
Build the applications using the makefile_VehicleModeling_<platform>
file.
For example:
$ make -f makefile_VehicleModeling_arm64Darwin20clang12.0
To generate the build files for the C# example, specify a
target platform. For example, net8
or net6
.
$ rtiddsgen -language 'C#' -example net8 VehicleModeling.xml
-example
will generate three different things:
A set of files for your data types.
An example publisher application, subscriber application, and QoS configuration for these.
A set of files to build and run these example applications.
Once the code is generated, build the example applications generated by rtiddsgen using dotnet.
$ dotnet build
Error NU1301
Unless you have installed the Connext .NET Support package, the NuGet.Config file generated by rtiddsgen will point to a directory in the Connext installation that may not exist.
If you encounter an error like NU1301
when building the application,
delete the file NuGet.Config file so that .NET gets the Connext NuGet package from nuget.org.
To generate the build files for the Java example, specify a target platform. For example:
Linux:
x64Linux4gcc7.3.0
,armv8Linux4gcc7.3.0
Windows:
x64Win64VS2017
macOS:
x64Darwin20clang12.0
,arm64Darwin20clang12.0
$ rtiddsgen -language Java -example x64Linux4gcc7.3.0 VehicleModeling.xml
-example
will generate three different things:
A set of files for your data types.
An example publisher application, subscriber application, and QoS configuration for these.
A set of files to build and run these example applications.
Once the code is generated, build the example applications generated by rtiddsgen using Ant.
$ ant compile
To generate the build files for the C example, specify a target platform. For example:
Linux:
x64Linux4gcc7.3.0
,armv8Linux4gcc7.3.0
Windows:
x64Win64VS2017
macOS:
x64Darwin20clang12.0
,arm64Darwin20clang12.0
$ rtiddsgen -language c -example x64Linux4gcc7.3.0 VehicleModeling.xml
-example
will generate three different things:
A set of files for your data types.
An example publisher application, subscriber application, and QoS configuration for these.
A set of files to build and run these example applications.
Once the code is generated, build the example applications generated by rtiddsgen for your platform.
Build the applications using the makefile_VehicleModeling_<platform>
file.
For example:
$ make -f makefile_VehicleModeling_x64Linux4gcc7.3.0
Open VehicleModeling-<platform>.sln
in Visual Studio and
compile the project.
Build the applications using the makefile_VehicleModeling_<platform>
file.
For example:
$ make -f makefile_VehicleModeling_arm64Darwin20clang12.0
The generated example consists of two simple applications using the last type
you defined (VehicleMetrics
):
A publisher that sends data for one of the types.
A subscriber that prints the received data in the console.
Run the applications:
First, run the publisher:
$ python VehicleModeling_program.py --pub
You should see the following output:
Running VehicleMetricsPublisher on domain 0
Writing VehicleMetrics, count 0
Writing VehicleMetrics, count 1
Writing VehicleMetrics, count 2
While the publisher is running, run the subscriber in another terminal:
$ python VehicleModeling_program.py --sub
You should see the data being received:
Running VehicleMetricsSubscriber on domain 0
Hello World subscriber sleeping for 1 seconds...
Received: VehicleMetrics(vehicle_vin='', fuel_level=0.0)
Hello World subscriber sleeping for 1 seconds...
Hello World subscriber sleeping for 1 seconds...
Received: VehicleMetrics(vehicle_vin='', fuel_level=0.0)
Hello World subscriber sleeping for 1 seconds...
Hello World subscriber sleeping for 1 seconds...
Update the publisher to write different samples by modifying the
code next to the comment # Modify the data to be written here
.
First, run the publisher:
$ objs/x64Linux4gcc7.3.0/VehicleModeling_publisher
You should see the following output:
Writing ::VehicleMetrics, count 0
Writing ::VehicleMetrics, count 1
Writing ::VehicleMetrics, count 2
While the publisher is running, run the subscriber in another terminal:
$ objs/x64Linux4gcc7.3.0/VehicleModeling_subscriber
You should see the data being received:
::VehicleMetrics subscriber sleeping up to 1 sec...
[vehicle_vin: , fuel_level: 0]
::VehicleMetrics subscriber sleeping up to 1 sec...
[vehicle_vin: , fuel_level: 0]
::VehicleMetrics subscriber sleeping up to 1 sec...
[vehicle_vin: , fuel_level: 0]
::VehicleMetrics subscriber sleeping up to 1 sec...
Update the publisher to write different samples by modifying the
code next to the comment // Modify the data to be written here
.
First, run the publisher:
$ dotnet run --pub
You should see the following output:
Running VehicleMetricsPublisher on domain 0
Writing VehicleMetrics, count 0
Writing VehicleMetrics, count 1
Writing VehicleMetrics, count 2
While the publisher is running, run the subscriber in another terminal:
$ dotnet run --sub
You should see the data being received:
Running VehicleMetricsSubscriber on domain 0
VehicleMetrics subscriber sleeping for 4 sec...
vehicle_vin: ""
fuel_level: 0
VehicleMetrics subscriber sleeping for 4 sec...
vehicle_vin: ""
fuel_level: 0
VehicleMetrics subscriber sleeping for 4 sec...
vehicle_vin: ""
fuel_level: 0
Update the publisher to write different samples by modifying the
code next to the comment // Modify the data to be written here
.
First, run the publisher:
$ ant VehicleMetricsPublisher
You should see the following output:
VehicleMetricsPublisher:
[java] Writing VehicleMetrics, count 0
[java] Writing VehicleMetrics, count 1
[java] Writing VehicleMetrics, count 2
[java] Writing VehicleMetrics, count 3
While the publisher is running, run the subscriber in another terminal:
$ ant VehicleMetricsSubscriber
You should see the data being received:
VehicleMetricsSubscriber:
[java] Received:
[java] vehicle_vin:
[java] fuel_level: 0.0
[java]
[java] No data after 1 seconds.
[java] Received:
[java] vehicle_vin:
[java] fuel_level: 0.0
[java]
[java] Received:
[java] vehicle_vin:
[java] fuel_level: 0.0
[java]
[java] No data after 1 seconds.
[java] Received:
[java] vehicle_vin:
[java] fuel_level: 0.0
[java]
Update the publisher to write different samples by modifying the
code next to the comment // Modify the data to be written here
.
First, run the publisher:
$ objs/x64Linux4gcc7.3.0/VehicleModeling_publisher
You should see the following output:
Writing VehicleMetrics, count 0
Writing VehicleMetrics, count 1
Writing VehicleMetrics, count 2
While the publisher is running, run the subscriber in another terminal:
$ objs/x64Linux4gcc7.3.0/VehicleModeling_subscriber
You should see the data being received:
VehicleMetrics subscriber sleeping for 4 sec...
Received data
vehicle_vin: ""
fuel_level: 0
VehicleMetrics subscriber sleeping for 4 sec...
Received data
vehicle_vin: ""
fuel_level: 0
VehicleMetrics subscriber sleeping for 4 sec...
Received data
vehicle_vin: ""
fuel_level: 0
VehicleMetrics subscriber sleeping for 4 sec...
Update the publisher to write different samples by modifying the
code next to the comment /* Modify the data to be written here */
.
The applications use a generic QoS profile defined in
the USER_QOS_PROFILES.xml
file. In the next section, you’ll define the
appropriate QoS for each Topic’s use case to complete your data model.
Troubleshooting
In case of errors building or running your application, make sure you have set up your environment and license file.
For instructions, go to Get Started, select your platform and installation method, then find the section Run a Hello World.
3. Define the quality of service for the data flows#
Different Topics may have different QoS requirements. For example, you may want to ensure that you reliably receive “Event” or “State” Topic samples, or that “Periodic” updates are produced at a regular interval.
For the VehicleMetrics
data flow, allow for some data to be
lost but also ensure that data is published at a steady rate. To do this,
use the Reliability and Deadline QoS policies.
In System Designer, select QoS in the View menu.
Using a similar workflow as you did adding new Types, create a new
QoS Library called VehicleModeling_Library
.
Then create a QoS Profile called VehicleMetrics_Profile
.
In the VehicileMetrics_Profile
add two new QoS for the
VehicleMetrics
data flow, one DataWriter QoS and one DataReader QoS.
<?xml version="1.0" encoding="UTF-8"?>
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://community.rti.com/schema/current/rti_dds_profiles.xsd">
<qos_library name="VehicleModeling_Library">
<qos_profile name="VehicleMetrics_Profile">
<datareader_qos base_name="BuiltinQosLib::Generic.BestEffort">
<deadline>
<period>
<sec>15</sec>
<nanosec>0</nanosec>
</period>
</deadline>
</datareader_qos>
<datawriter_qos base_name="BuiltinQosLib::Generic.BestEffort">
<deadline>
<period>
<sec>10</sec>
<nanosec>0</nanosec>
</period>
</deadline>
</datawriter_qos>
</qos_profile>
</qos_library>
</dds>
With this QoS configuration:
Communication will be best effort, meaning that the publisher won’t attempt to resend a data sample if the subscriber misses it.
Publishers will be expected to produce data every ten seconds, while subscribers allow for 15 seconds between each data reception. A status will be triggered if either deadline is missed, allowing your applications to act accordingly.
For the VehicleTransit
data flow, ensure that no data is lost even though subscribers may only be interested in the last available state. To do this,
use the Reliability, Durability, and History QoS policies.
In the same VehicleModeling_Library
QoS Library, add a new
VehicleTransit_Profile
QoS Profile.
Add two new DataWriter and DataReader QoS configurations:
<?xml version="1.0" encoding="UTF-8"?>
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://community.rti.com/schema/current/rti_dds_profiles.xsd">
<qos_library name="VehicleModeling_Library">
<qos_profile name="VehicleTransit_Profile">
<datareader_qos base_name="BuiltinQosLib::Generic.KeepLastReliable">
<durability>
<kind>TRANSIENT_LOCAL_DURABILITY_QOS</kind>
</durability>
</datareader_qos>
<datawriter_qos base_name="BuiltinQosLib::Generic.StrictReliable">
<durability>
<kind>TRANSIENT_LOCAL_DURABILITY_QOS</kind>
</durability>
</datawriter_qos>
</qos_profile>
</qos_library>
</dds>
With this QoS configuration:
Communication will be reliable, meaning that the publisher will expect an acknowlegment from the subscriber for each data sample. If a sample is acknowledged as lost, the publisher will resend it.
Publishers will keep as many data samples as needed in memory to ensure reliable delivery with active subscribers. Additionally, publishers will deliver the latest update to any new subscriber.
After defining the QoS profiles, update the publisher and subscriber applications to load the VehicleMetrics_Profile
profile.
Update VehicleModeling_publisher.py
to replace the creation of the DataWriter with the following code:
qos_provider = dds.QosProvider("VehicleModeling.xml")
writer_qos = qos_provider.datawriter_qos_from_profile(
"VehicleModeling_Library::VehicleMetrics_Profile"
)
writer = dds.DataWriter(participant.implicit_publisher, topic, writer_qos)
Update VehicleModeling_subscriber.py
to replace the creation of the DataReader with the following code:
qos_provider = dds.QosProvider("VehicleModeling.xml")
reader_qos = qos_provider.datareader_qos_from_profile(
"VehicleModeling_Library::VehicleMetrics_Profile"
)
reader = dds.DataReader(participant.implicit_subscriber, topic, reader_qos)
Update VehicleModeling_publisher.cxx
to replace the creation of the DataWriter with the following code:
dds::core::QosProvider qos_provider("VehicleModeling.xml");
dds::pub::qos::DataWriterQos writer_qos = qos_provider.datawriter_qos(
"VehicleModeling_Library::VehicleTransit_Profile");
dds::pub::DataWriter< ::VehicleTransit> writer(
publisher,
topic,
writer_qos);
Similarly, update VehicleModeling_subscriber.cxx
to replace the creation of the DataReader with the following code:
dds::core::QosProvider qos_provider("VehicleModeling.xml");
dds::sub::qos::DataReaderQos reader_qos = qos_provider.datareader_qos(
"VehicleModeling_Library::VehicleTransit_Profile");
dds::sub::DataReader< ::VehicleTransit> reader(
subscriber,
topic,
reader_qos);
Update VehicleMetricsPublisher.cs
to replace the creation of the DataWriter with the following code:
QosProvider qosProvider = new QosProvider("VehicleModeling.xml");
DataWriterQos writerQos = qosProvider.GetDataWriterQos("VehicleModeling_Library::VehicleTransit_Profile");
DataWriter<VehicleMetrics> writer = publisher.CreateDataWriter(topic, writerQos);
Update VehicleMetricsSubscriber.cs
to replace the creation of the DataReader with the following code:
QosProvider qosProvider = new QosProvider("VehicleModeling.xml");
DataReaderQos readerQos = qosProvider.GetDataReaderQos("VehicleModeling_Library::VehicleTransit_Profile");
// This DataReader reads data on Topic "Example VehicleMetrics".
// DataReader QoS is configured in USER_QOS_PROFILES.xml
DataReader<VehicleMetrics> reader = subscriber.CreateDataReader(topic, readerQos);
Update VehicleMetricsPublisher.java
to replace the creation of the DataWriter with the following code:
DomainParticipantFactory factory = DomainParticipantFactory.get_instance();
DomainParticipantFactoryQos factoryQos = new DomainParticipantFactoryQos();
factory.get_qos(factoryQos);
factoryQos.profile.url_profile.add("VehicleModeling.xml");
factory.set_qos(factoryQos);
DataWriterQos writerQos = new DataWriterQos();
factory.get_datawriter_qos_from_profile(
writerQos,
"VehicleModeling_Library",
"VehicleMetrics_Profile");
// This DataWriter writes data on "Example VehicleMetrics" Topic
VehicleMetricsDataWriter writer = (VehicleMetricsDataWriter) Objects.requireNonNull(
publisher.create_datawriter(
topic,
writerQos,
null, // listener
StatusKind.STATUS_MASK_NONE));
Update VehicleMetricsSubscriber.java
to replace the creation of the DataReader with the following code:
DomainParticipantFactory factory = DomainParticipantFactory.get_instance();
DomainParticipantFactoryQos factoryQos = new DomainParticipantFactoryQos();
factory.get_qos(factoryQos);
factoryQos.profile.url_profile.add("VehicleModeling.xml");
factory.set_qos(factoryQos);
DataReaderQos readerQos = new DataReaderQos();
factory.get_datareader_qos_from_profile(
readerQos,
"VehicleModeling_Library",
"VehicleMetrics_Profile");
// This DataReader reads data on "Example VehicleMetrics" Topic
reader = (VehicleMetricsDataReader) Objects.requireNonNull(
subscriber.create_datareader(
topic,
readerQos,
null, // listener
StatusKind.STATUS_MASK_NONE));
Update VehicleModeling_publisher.c
to replace the creation of the DataWriter with the following code (error checking omitted for brevity):
struct DDS_DomainParticipantFactoryQos factory_qos =
DDS_DomainParticipantFactoryQos_INITIALIZER;
DDS_DomainParticipantFactory_get_qos(
DDS_TheParticipantFactory,
&factory_qos);
DDS_Long factory_qos_url_profile_length =
DDS_StringSeq_get_length(&factory_qos.profile.url_profile);
DDS_StringSeq_ensure_length(
&factory_qos.profile.url_profile,
1 + factory_qos_url_profile_length,
1 + factory_qos_url_profile_length);
*DDS_StringSeq_get_reference(
&factory_qos.profile.url_profile,
factory_qos_url_profile_length) = "VehicleModeling.xml";
DDS_DomainParticipantFactory_set_qos(
DDS_TheParticipantFactory,
&factory_qos);
struct DDS_DataWriterQos writer_qos = DDS_DataWriterQos_INITIALIZER;
DDS_DomainParticipantFactory_get_datawriter_qos_from_profile(
DDS_TheParticipantFactory,
&writer_qos,
"VehicleModeling_Library",
"VehicleMetrics_Profile");
writer = DDS_Publisher_create_datawriter(
publisher,
topic,
&writer_qos,
NULL /* listener */,
DDS_STATUS_MASK_NONE);
Similarly, update VehicleModeling_subscriber.c
to replace the creation of the DataReader with the following code (error checking omitted for brevity):
struct DDS_DomainParticipantFactoryQos factory_qos =
DDS_DomainParticipantFactoryQos_INITIALIZER;
DDS_DomainParticipantFactory_get_qos(
DDS_TheParticipantFactory,
&factory_qos);
DDS_Long factory_qos_url_profile_length =
DDS_StringSeq_get_length(&factory_qos.profile.url_profile);
DDS_StringSeq_ensure_length(
&factory_qos.profile.url_profile,
1 + factory_qos_url_profile_length,
1 + factory_qos_url_profile_length);
*DDS_StringSeq_get_reference(
&factory_qos.profile.url_profile,
factory_qos_url_profile_length) = "VehicleModeling.xml";
DDS_DomainParticipantFactory_set_qos(
DDS_TheParticipantFactory,
&factory_qos);
struct DDS_DataReaderQos reader_qos = DDS_DataReaderQos_INITIALIZER;
DDS_DomainParticipantFactory_get_datareader_qos_from_profile(
DDS_TheParticipantFactory,
&reader_qos,
"VehicleModeling_Library",
"VehicleMetrics_Profile");
reader = DDS_Subscriber_create_datareader(
subscriber,
DDS_Topic_as_topicdescription(topic),
&reader_qos,
&reader_listener,
DDS_STATUS_MASK_ALL);
Running your applications as you did in the previous section, you’ll see similar output. However, under the hood, the actual behavior is different and subject to the QoS you’ve defined.
These applications publish and subscribe to the VehicleMetrics
Topic.
You can create similar applications for the VehicleTransit
topic, or you can
continue this exercise in the Application Design module, where you’ll use
System Designer to define both Topics and their DataReaders and DataWriters,
and instantiate these in your application.
Learn More#
You have learned how to define the data model for a simple vehicle tracking system, generate example applications, and define the quality of service for the data flows.
Next Steps
Related modules:
Application Design builds on this module, showing how to use System Designer to define Topics, DataReaders, and DataWriters to create a full application.
Full code examples:
Reference documentation:
More resources: