Matrix Board Communication in C++¶
authors: | Joost Baars |
---|---|
date: | June 2020 |
Description¶
This page describes the matrix board demonstrator in C++. The matrix board demonstrator is explained in Matrix Board Communication. This page starts with how the application can be built and executed. Afterward, the structure of the application is described in detail.
The matrix board C++ directory can be found in src/demonstrators/MatrixBoard/C++/
.
This directory contains the matrix board application in C++.
This matrix board application contains a similar implementation compared to the
poc3
of the C implementation (Matrix Board Communication in C). Therefore, this is a
dynamic implementation of the matrix board application.
Dependencies¶
The necessary dependencies for succesful compilation of the matrix board application in C++ are the following:
- CMake
- C++17 compiler (Gcc 7+ for example)
- Cyclone DDS library
Installing Cyclone DDS and the other dependencies can be found in: Clean Install with internet.
Building¶
First, go to the C++ matrix board directory (see Description).
Execute the following commands:
mkdir build && cd build cmake .. make
These commands compile the code and create the executable for the C++ matrix board application.
Execution¶
The application must be executed using one parameter. The application can be executed using the following command:
./MatrixBoard <Matrixboard ID>
A more thorough description of the parameters can be found when executing the application with no parameters.
Note
Execution of the program
The <Matrixboard ID> parameter should be unique for every matrix board. Additionally, it may not be less than 1.
The order at which matrix boards are started does not matter.
Example¶
For example, two matrix boards can be started to see the communication between the two applications.
Open two terminals and go to the location where you built the matrix board application.
Execute the following in one terminal
./MatrixBoard 10
And the following command in the other terminal:
./MatrixBoard 15
When the second matrix board is started, logging should be shown. The logging that can occur is described in the chapter below.
Logging information¶
The matrix board application prints information to the terminal/standard output. This logging contains information that is classified with different tags.
Each tag is described below.
INFO
The INFO tag shows general information of the matrix board. It contains a starting message. The INFO tag is also used to display the speed of the matrix board. If the maximum speed changes, the new maximum speed is printed using the INFO tag.
When new traffic data is received, it is also shown with the INFO tag. The newly received traffic data is printed towards the terminal including the matrix board ID from which the traffic data came.
CONNECTED or DISCONNECTED
The CONNECTED and DISCONNECTED tag are shown when changes occur with the subsequent matrix boards.
An example of the logging can be seen below. In this example, only one subsequent matrix board is connected. There is no second subsequent matrix board on the network. The connected subsequent matrix board has an ID of 5.
[2020-06-04 00:10:07.677]: CONNECTED: Subsequent matrix board: 5
[2020-06-04 00:10:07.678]: DISCONNECTED: After the subsequent matrix board disconnected!
Each of the two subsequent matrix boards has its own message regarding if it is connected or not.
ERROR
The ERROR tag is used to show that an error occurred with the communication or the matrix board.
Implementation¶
This matrix board implementation works dynamically. Therefore, the order of adding matrix boards does not matter as well as the ID’s of the matrix boards.
For example, a matrix board with ID 1 can have a matrix board with ID 1000 as the subsequent matrix board (if no other matrix boards exist in between).
In the deployment diagram below, the communication between different sub-classes can be seen. The clouds in the diagram are the different DDS topics. This diagram only shows the communication of one of the matrix boards.
This diagram shows that there is one “global” topic, which is a topic that does not belong to a specific matrix board. All matrix boards write to that topic once at the beginning of their lifecycle. Afterward, they only read the ID’s of the other matrix boards from that topic.
The other topics belong to a matrix board. The matrix board that belongs to the topic (same ID) writes its sensor data to that topic. The preceding two matrix boards read the data from that particular topic.
The debug topic can be used to calculate the time between connecting and being connected to a topic. As well as disconnecting and being disconnected from a topic. This is not done in the matrix board application, but the possibility is there because of the debug topic.
Class diagram¶
The class diagram is shown below. This class diagram shows that the intelligence
of the system is the MatrixBoard
class. This class executes everything and
contains a run()
function that runs the matrix board application.
Each part of DDS is separated into its own class. This is divided into 2 classes and one abstract base class.
The ActiveMatrixBoardManager class manages the “global” topic and can return the ID’s of the two subsequent matrix boards.
The DDSActiveMatrixBoard class manages the DDS part of the “global” topic.
The SpecificMatrixBoard manages a matrix board topic with a certain ID. This class can read and write from the topic it is connected to. This class is used for the 2 subsequent matrix boards (read-only) and for its own matrix board (write-only). Therefore, there are 3 classes of these.
There are two packages in this class diagram. One for the matrix board functionalities. The other is the debug package. The DebugTopicManager class can be used for sending debug messages to a DDS debug topic (using the DebugTopicDDS class). The DebugTopicManager class is a fully static class, so the debug functions are easily accessible in the matrix board.
Global topic / ActiveMatrixBoards class¶
This chapter describes the application in a technical manner.
The ActiveMatrixBoards
class contains the logic for defining the
subsequent 2 matrix boards. This class uses the DDSActiveMatrixBoard class
for communication with the “global” topic.
The settings for the “global” topic are configured in the DDSActiveMatrixBoard class. The “global” topic is configured to have a history of 1 and a durability transient local. The history of 1 ensures that the last message of each writer is stored and can be resent. The durability transient local ensures that if a new reader connects, it receives previously send messages from the writer. This durability setting also specifies that the previously sent messages are stored by the writer. This is important because if the writer disconnects, we don’t want to see it’s message anymore. This combination makes sure that the last message of a writer is resent to a newly connected reader, but only if that writer still exists.
Each matrix board only writes once to the “global” topic, containing the ID of that matrix board. This message will automatically resend if a new matrix board connects (this is done by DDS). Therefore, all matrix boards know the ID of every other matrix board. Because when they connect, they receive the last message of each matrix board (containing the ID). And if they are alive when a new matrix board connects, it just reads the message of the newly connected matrix board.
The liveliness is also configured for the “global” topic. This is used for removing disconnected matrix boards and reconnecting to a different matrix board that is alive. DDS uses handles for each DDS instance. This handle is added to every DDS message and is also added to the liveliness status. Therefore, this can be used to know what matrix board disconnected when the liveliness changes.
The ActiveMatrixBoardManager
class contains an ordered map with the ID and the
handle of each matrix board. When a matrix board disconnects, this matrix board
is removed from the map based on its handle. This map is ordered based on the
ID of the matrix board. Therefore, the subsequent matrix boards can easily be
found within the map. Scalability wise, this map becomes larger as more matrix
boards are on the network. Therefore, this method is not ideal for a fully
scalable matrix board network.
When the ActiveMatrixBoardManager
class registers to the topic, it reads all
existing messages from the topic and fills the ordered map with the existing
matrix boards. If there is a liveliness update, it checks if a device is added
or removed. If a device got added, it reads the new message on the topic. If
a device got removed, it reads the handle of the disconnected matrix board and
removes that device from the map. Afterward, it checks if the subsequent
matrix boards got changed. If so, this is updated to the new ID’s.
MatrixBoard class¶
This class executes everything and contains the run
loop for the matrix
board application.
At the beginning of the run loop, the registerToTopic()
functions are
executed for both the OwnMatrixBoard
and the ActiveMatrixBoards
classes.
This initializes DDS to register to the topic. Furthermore, a timer is
initialized to send the traffic data to its own topic with a certain interval.
This timer is set on 1 second. So traffic data is sent to its own topic every
second.
There are mainly 3 parts in the matrix board run
loop. The first is
checking the timer. If the timer has passed, the newest sensor data is
requested and send to its own topic using the OwnMatrixBoard
class.
Additionally, the display of the matrix board is also updated in this timer.
The second part is checking for updates on the “global” topic. This is done by
executing the checkChanges()
function in the ActiveMatrixBoards
class.
If there are changes, the `SpecificMatrixBoard
objects that point to the
subsequent matrix boards are updated. These objects are stored in a so-called
smart-pointer which handles the allocation and deallocation of the resource.
This smart-pointer is simply set to a new SpecificMatrixBoard
object when
the ID’s of the subsequent matrix boards changes.
The third and last part of the run
loop reads the traffic data from the 2
subsequent matrix boards (if they exist). First, the smart-pointer is checked
if there is an object stored. If so, the checkNewData()
function from the
SpecificMatrixBoard
class is executed. At last, this data is read using
getLastMessage()
function if new data is received. If there was no object
stored in the smart-pointer in the first place, then nothing would happen. As
there is apparently no subsequent matrix board.
Specific Matrixboard class¶
This class connects to a specific matrix board topic. Each matrix board is connected to its own topic and writes its own sensor data towards that topic. Additionally, each matrix board is connected to 2 subsequent matrix board topics (if they exist). Therefore, there are a maximum of 3 specific matrix board objects created.
The specific matrix board class creates its own DDS participant. This is done because specific matrix board objects should be easily deletable and new objects for different topics should be easily creatable. If the participant was not managed by the specific matrix board, then the previously allocated readers or writers of the specific matrix board would stay alive when the specific matrix board object would be removed. This results in no liveliness change when it should. Additionally, this would use more memory and would have a negative impact on the dynamic aspect of the matrix board application.
The specific matrix board has by default a liveliness callback function for the writer and a different callback function for the reader. The reader gets a callback if the liveliness changes of the writer on the topic. The writer gets a callback when a reader connects or disconnects from the topic. The use of these callbacks are only the debug messages. To detect when a device connects/disconnects from a certain topic.
Debug topic¶
The class diagram also contains a debug topic. This debug topic is added for debug purposes. A timestamp is sent to the debug topic when a matrix board connects to a specific matrix board topic and when it is connected to that topic. When a device disconnects from the specific matrix board topic, a timestamp is also sent to the debug topic.
The debug functionalities can be used to see when a device connects or disconnects. Additionally, the time of connecting/disconnecting can be measured.