In this laboratory lesson, we will implement our first rose to node in Python that will use the publisher
subscriber communication protocol to publish a message within a ros2 topic.
If you are only interested in the cplusplus software development, then you can skip directly to the
next lesson where we will implement the same node with the same functionalities in C plus plus.
Let's start by opening Visual Studio code.
And here let's open the robots workspace.
So let's open the folder that is called Arduino Bot Workspace.
Inside the workspace within the source folder.
So here we created already the two packages, Arduino bot, CP examples and the Arduino bot Pi examples
with the Ros two package create command in the previous lesson and this already created also several
folders and several files within the two packages.
The files and the folder created in the Arduino Pi example is the typical structure of any Python package
used in Ros2.
So there is a sub folder which has the same name of the package.
So in this case Arduino Pi examples and this will contain the source code.
So all the Python scripts that we are going to develop.
So here let's create also a new file and let's call it simple publisher dot pi to indicate that it is
a python file here.
Let's start by importing the Pi library.
Which will allow us to use all the ros2 functionalities within our Python script.
Then still from the rql py library.
This time from the node module.
Let's import the node class and we can use this class to create a new ros2 node.
So let's create a new class called for example Simple publisher and let's make this class inherit from
the node class of the Pi library.
So in this class, let's first define the constructor of the class.
So the function that is automatically executed when a new object of the class is created.
So this is called the init function.
And here.
So when we initialize a new object of type simple publisher, the first thing we do is to initialize
the components of the base class.
So namely the components of the node class from which the simple publisher is inheriting.
So let's call the super init that will call the constructor of the node class and let's assign a name
to our node that we call Simple Publisher.
Now that we have initialized the Ros two node class, let's create a new publisher object.
So let's create a new variable.
And to initialize a publisher object.
Let's use the create publisher function that is defined in the node class from which we are inheriting.
So let's use the create.
Publisher function.
And in this function we need to indicate the message type.
So the type of the interface that we need to use for the message exchange with the topic.
In practice, we need to specify which type of messages the publisher object will send through the topic.
For example, let's say that we want to send text messages, so we want to send strings.
The string message is contained, is defined in another Ros two library.
So let's import it from the standard messages library from the messages that are defined in this library.
Let's import the string message.
And let's use it to indicate that within the create publisher function we are going to use string messages
to interact with the topic.
We also need to specify the name of the topic in which we want the messages to be published.
So, for example, let's call this one chatter.
Furthermore, we also need to indicate the size of the queue, namely the size of the message queue
that works as a buffer.
If the subscriber to this topic is not receiving and processing messages fast enough.
Let's set this 1 to 10.
Let's add some more supporting variables to the simple publisher class, and let's call the first one,
the variable counter that we initialize to zero, and it will count the number of messages that we are
going to publish within the topic.
Then let's also define a frequency variable
that we initialize to 1.0, so to one hertz, and this one will define the frequency at which we want
to publish messages within the topic.
So we are going to publish them at a frequency of one hertz.
So we are going to publish one message per second within the chapter topic.
At this point during the initialization of the node.
Let's also print an informative message in the terminal using the get logger function, which we are
still inheriting from the node class.
So let's use the get logger function.
And then from this one let's use the info function to print an informative message in the terminal.
And the message says publishing at.
And then the number of earths that we are using.
So followed by the variable frequency.
Lastly, inside the constructor of the Simple Publisher class, let's also create a new timer object
using the create timer function.
So let's call this one timer.
And still from the node class, let's use the create timer function.
So they create timer function takes as input the frequency at which we want to execute a certain function
and we store this one in the frequency variable and it also takes the name of the function to be executed
at regular time intervals.
So at each expiration of the timer, so at a frequency of one hertz and let's call this function timer
callback.
With this, the constructor of the simple publisher class is completed and we can proceed to define
the timer callback function, which will be the one that is repeatedly executed with a frequency of
one hertz by the timer object.
So let's define this function, the timer callback function.
And this is a member of the simple publisher class and the goal is to publish a new message within the
chapter topic every time this function is called.
So every time this function is executed by the timer.
So here, let's start by creating a new message to be published within the topic.
So let's call this variable message and this is of type string.
So from the string interface that is defined in the standard messages.
And now let's publish, for example, the message that says Hello Ross to and then let's also print
the counter.
And so let's print the variable that we called counter.
Then with this done, we can use the publish function of the publisher object.
So of this object here.
Let's call the publish function to publish the message we just created.
So the variable MSG.
And then once we have published the message within a topic, let's also increment the counter variable
by one since we have just published a new message.
With this.
The simple publisher class is complete and now we can proceed to define the main function.
And so the one that is automatically called upon the execution of this script.
So.
And here let's call the main function.
So let's execute the main function.
But first let's define this main function.
And here as our first step, let's initialize rows using the init function from the PY library.
So from rql py.
Let's use the init function to instantiate the communication with rows and then let's create a new object
of the simple publisher class.
So let's call this variable simple publisher and is an instance of the simple publisher class and let's
keep this node up and running.
So keeping the timer and the publisher active so that they can continuously send messages within the
chapter topic.
And to do so we can use still from the PY library the spin function to keep the simple publisher node
up and running.
Finally, if we terminate the execution of the node by pressing Ctrl Z in the terminal, we need to
ensure that also the simple publisher node is properly destroyed.
So let's call the function destroy node on the simple publisher function.
And also in this case, let's shut down Ros two.
Let's save this script.
And now in order to execute this node, we first need to instruct the compiler on how it should build
our script to make it an executable in Ros.
To.
To do so, we need to modify another file that was automatically created within the Arduino bot Pi examples
package.
And this is the Setup.py file.
You can think of this file as a kind of instruction sheet that tells the compiler how to translate our
Python scripts into executable files.
To do this in the entry points section in the console script list.
Let's add a new executable.
So here, let's add a new one and let's call this one simple publisher.
And the script that we want to install is located within the Arduino Boot Pi examples folder.
Then within the simple publisher file.
And from this one we want to start.
So we want the starting point to be the main function.
So let's save also this file.
And finally, before actually building the workspace and starting the node, we also need to declare
the dependencies of the new node.
So namely, we need to declare the libraries that it uses for its execution.
To do this, we need also to modify the file that was automatically created and that is called package
dot XML and that is still in the Arduino dot pi example package.
Here.
We need to add some dependencies, some execution dependencies.
And let's start by adding the one from the Pi library, which we used in our script and which allowed
us to use all the functionalities within the Python script.
Also, let's add another exec dependency from the standard messages library from which we use the declaration
of the string message.
Let's save also this file.
And these are the only two libraries that we need in the simple PowerShell script so we can finally
execute our node.
So let's open a new terminal.
Let's go to the workspace and let's run the command on build.
So this will build the entire workspace again, including also the new node.
And now to execute the node, let's split the terminal.
So let's take another terminal.
Here, let's source the workspace.
So let's source the file setup dot bash that is in the install folder.
And this way the Arduino board by example is recognized.
And so we can execute now the script, the nodes that it contains.
To start a ros2 node, we can use the command Ros to run followed by the name of the package where the
node is located, which in our case is the Arduino bot pi examples so we can use Tab to exploit the
Ros2 Autocompletion.
Then if we press tab twice we can see that the simple publisher node is recognized.
So let's execute the simple publisher node.
So let's press enter to start the node.
And as you will see, it appears the message publishing at one hertz in the terminal and to verify that
indeed the node is publishing a message within the charter topic, we can split our terminal again and
we can take a look at all the topics that are currently available in Ros2 with the command Ros2.
Topic list.
So let's press enter.
And as the name of the command suggests, it will show all the topics available in Russia at this moment.
And among these topics, we can see that it appears the chapter topic, which is exactly the name we
gave to the topic in the publisher node.
If we stop, for example, the execution of our publisher node and we execute again, the command Ros2
topic list.
Now, as you can see, the chatter topic is no longer available since the node that was publishing messages
on it is no longer running.
So let's relaunch the node again and let's use again the Ros2 topic list and the chatter topic is back
on track.
We can also take a look at which are the messages that are currently traveling within this topic using
the command Ros2 topic Echo followed by the name of the topic, which is chatter.
So let's press enter and all the messages that are now published within this topic are now printed in
the terminal.
And so we can see that each message contains the string l0 ros2 followed by the counter that is increasing
at each new message that is being published.
Now, if we stop again, the execution of the node, we can see that there are no new messages published
within the topic and it will restart as we restart here the node.
There are other two useful ros2 commands that we can use to provide additional information about a topic,
and these are ros2 topic info still followed by the name of the topic from which we want to obtain more
info.
So for example the chatter topic.
And here we can see the type of the message that is being published.
And also, if we use the verbose flag, we get even more information about it.
So for example, we get the name of which Node is interacting with this topic that in this case is the
simple publisher node.
Finally, the last command that we are going to use in this lesson is the Ros2 topic.
Earth's still followed by the name of the topic.
So chatter, let's press enter and this command analyzes the messages that are published in the chatter
topic and calculates the frequency at which they are published.
In this case, as we can see, it is calculating a frequency so an average rate of one hertz, which
is exactly the value that we set for the timer in the Visual Studio code.
So here we set the frequency of one hertz.