In this lecture, we will create our very own Roth publisher node.
We'll make a simple publisher that publishes a string that says Hello World, followed by a number which
increments up every time we publish.
Then in a future lecture, we'll create a subscriber to receive the messages we publish.
For now, let's open up our Visual Studio code editor.
Go over to file.
Open folder and we will open up our Ras two Pi workspace folder.
Go ahead and trust the workspace.
And for now we're going to skip configuring our C make environment.
So for now, just go ahead and cancel that and hit escape.
And now we see all of our folders from our project workspace directory here in the left side panel.
Now notice it's also generated a hidden VS code folder.
This contains all the setting configurations for our Visual Studio Code editor and you can see it within
the file Explorer by hitting Control H or by heading over to the three dashes and checking or unchecking
show hidden file.
So now we can't see that hidden file.
So the first thing I can go ahead and do is open up the source folder, which takes us into our RAS
two package and we can go into the scripts folder.
So currently we don't have any.
So I'll go ahead and right click hit new file and I will just create a new script called Publisher Spy.
Just a pre face all RAR to Python functionality is documented in the RCL py API documentation.
Here you can review specific functionality of things.
We are going to be using in the RAS two Python library, including additional arguments and how they
work.
But for now, I'm just going to go through and show you how this functionality works first hand.
But if you have additional questions, feel free to reference that documentation page.
In order to use raw features in Python, we need to import the ROS client library python module.
This is abbreviated as rcl py.
Within the script I will create a standard python if name is equal to main call and within it I will
just call a function called main.
You'll see my reasoning for doing this later in the course.
So let's create the main function above.
All right.
The first thing we're going to do in our main function is initialize our Ros RDS communications.
We can do this by calling our ROS client library and using the init function.
This has two optional arguments which can be put in command line arguments and a context name we won't
use either.
So we'll just leave this function as is with no parameters in it.
OC We are configured to be able to use ROS functionality, so let's actually create our node.
The ROS client library contains a node class with all the different ROS functionality to implement in
our code.
So what we can do is create our own class which inherits all the functionality of that existing ROS
node class.
I'll create the class above and call it Hello World Publisher.
Now I need to pass it in the node class to inherit its functionality, so I will first import it in
from the ROS client library.
Like so.
Now I can pass this node class into our Hello world publisher for it to inherit it.
The first thing to do in any Python class object is to create our init function.
And the first thing we will do is initialize the node.
So we will use Python's super function to gain access to the init method from that node object we inherited
from ROS client library.
And just as a side note, by default, Vee's code will set the spaces to four.
I'd like to prefer using tabs instead of spaces.
So if I go ahead and highlight this, you can actually see individual dots which represent the spaces
for which our code is organized.
So if you want to change that, I'll just go ahead and hit shift tab and re tab that back in.
And now instead of these spaces we are seeing the actual tab marks and I'll go ahead and do that for
these lines as well.
So this is totally personal preference, if you like, spaces versus tabs.
But I figured it was worth noting for those of you who are new to Visual Studio Code.
Now back to this node in IT object.
So the node object can take in several different optional parameters and I can actually see that by
going ahead and deleting these parentheses right now and recreating them.
And here we see VS Code gives us a dialog window of all the optional parameters we can put in here.
Now of course you could also check the SQL Pie Docs page for more information.
However, the only required arguments is what we want the name of the node to be.
In this case, let's name it.
Hello World Pub Node.
Now our node is initialized.
Let's create our publisher.
I will create a class member variable called pub and set it equal to the self dot create publisher function
which we inherited.
When we initialize the node above the create publisher Command takes in three required arguments.
The first is the ROS message type we want for our publisher.
Since we want to publish a hello world message, we can use the ROS string message type.
We will learn more about ROS message types in future lectures.
For now I will just import the string message from the standard messages ROS library and use it in our
create publisher function.
The second parameter is the topic name we want to publish over.
I will just call it Hello World.
Note that the topic nor node name can have spaces in them, which is why I use underscores to separate
words.
Now, the last argument for our publisher is the shows profile size cross stands for quality of Service.
COS serves a similar purpose as the queue size did in Ross, one in which we are setting a queue depth
to save old messages.
That way, if our robot is on an unstable network connection between other raw systems, when we regain
connection, we can get a backlog of the published messages.
In this case, I will just set our publisher queue size to ten.
With that, our publisher is actually created.
Now we want to tell our node to keep publishing our Hello world message at a certain rate.
This used to be done in Ross one using a rate object and a while loop to have your nodes keep completing
the action within the while loop at the desired rate in Ross to a timer functionality was added to help
simplify this so we can create a timer variable and set it equal to our nodes.
Create timer function.
This function takes in two parameters the rate of our timer in seconds and the callback function We
want to run at that rate in this case, we're going to want to create a callback function to publish
our Hello world message.
So we will create a new function in our class called Publish Hello World.
You can see I set the rate to 0.5, which means that every 0.5 seconds this function will run.
So let's go ahead and create this function below.
The first thing we need to do before we publish any data is to create the message object we're going
to be using.
In this case, we are using a string from the Standard Messages library so we can initialize it like
so this string object only has one attribute which is called data.
So all we need to do to load our data into this variable is to set the string message data attribute
to the data we want to send.
In this case, a string saying Hello world.
Now that our message data is loaded, let's publish the message by using our pub variables publish function
which takes in our message.
Great.
So let's quickly review what's going on in this code.
So far we created a class called Hello World Publisher, which inherited the functionality of the node
object from the ROS client library.
We initialized our node, created a publisher which publishes string messages over the Hello world topic
and then created a timer which will run our publish Hello world function.
Within our publish.
Hello world function we create a string message load our hello world string data into the message and
then tell our publisher to publish this message.
Now, one more thing I will add to this is a counter to count up every time we publish a message so
we can see some variation in the data coming over this topic.
So I will create a counter variable when we initialize our class.
Then in our publish Hello world function, include it within our message data and add one after we publish
the message.
With that.
I am now done with my class.
So back in my main function I can create an instance of this class.
I will just call it my pub then to make it look a little bit nicer.
When we run this in terminal, let's print out that our publisher node is running.
Now we are going to want this Python script to keep running in the terminal until we tell it to stop
by hitting control.
C So to stop our Python scripts from finishing right after we create our My Pub variable, I will use
the ROS client library spin function, which we will run until there is a keyboard interrupt.
So I will wrap it in a try except statement like so.
Now, when there is a keyboard interrupt, I'm going to want to stop my node by calling the destroy
node function.
With that, I have finished my publisher script, so let's save it, which you can do with either the
control se shortcut key or by heading over to file and save.
And then we can go ahead and open up a terminal and then we'll change it to the directory which our
script is located in and run the Python three command, followed by the name of our script, which is
publisher Pi OC.
We ran the command and got that the publisher node running.
Print it to the screen.
We can check this by opening a new terminal tab.
And using the Ross to node list command.
Here we see.
Hello World Pub node is one of the nodes running and that's the name we defined when we called our init
method from the node class we inherited.
You can also check for topics by using the ROS two topic list command.
And here we see our default ROS out and parameter events topics which you'll see by default when ROS
is running.
And our Hello world topic which we defined for our publisher here.
Last but not least, we can see the data coming in over the topic by running the Ross two topic Echo
command, followed by the name of the topic, which as we know is Hello World.
And here we see the Hello World data coming in, as well as this number incrementing up with each time
it prints out.
So I'll go ahead and stop that with control C And to stop your publisher node, you can click on that
terminal tab and hit Control C as well.
And we see the terminating nodes and now none of our nodes are running.
And if we run across to node list, we see that indeed our Hello world hub node has stopped.
Congratulations With that.
You have successfully created your very own Ras to publisher in Python.
In this lecture, we learned how to use the ROS client Library Python API to create a publisher node.
We imported the ROS client library, node class and string message types.
We'll talk a bit more about message types later on in the course.
Then we created our own class, which is based off of the ROS client libraries Node object.
We then use the super init call to initialize our node with a node name.
We then use the create publisher function, which takes in the message type, topic, name and queue
size.
And lastly, we utilize a create timer function to run a callback function at a particular rate.
In this callback function we initialize our message object, which in this case was our string message.
We then loaded the data attribute of it with the data we wanted to send.
Then we call the publish function of our publisher variable, which takes in the message object and
publishes it over Ros.
Lastly, within our main function we initialize our ROS communications and use the spin function to
keep the node running.
And then if an exception occurred, we then destroyed our node to stop our ROS communications.