Let's now improve this node with object oriented programming or OOP.
This will make your node more scalable, and it's the recommended way to write code in Ros2 as per the
official guidelines.
And any way you will see that all the codes well everywhere is using OOP.
So let's create a class here for our node.
And after we have this class, we will have the template that we can use for any nodes that we create
in the future.
So how do we create a class here.
Well I'm going to use the class keyword and let's name it my node.
So here I don't have any context.
So I use my node.
But for example if you would create a temperature sensor node well you would name it temperature sensor
node.
So that's the class that's going to inherit from the node class.
So that's very important.
So you inherit from the node class which means that you will be able to use all the Ros2 node functionality
from our CLP.
So we'll do this.
And then inside we have a def underscore.
Underscore init.
So that's the constructor for Python self.
Okay.
So this is the basic Python OOP stuff.
We create a constructor in this constructor.
The first thing we need to do is super we call the super.
So we call the parent constructor of the node class.
And we do init as well here like that.
And we pass here the node name.
So that's going to be pi test.
All right.
So we call the parent constructor here to initialize the node from the node class.
And that's it for the minimum code for a node.
Okay.
Now I'm also going to add this line here to use the logging functionality.
So how to use the logging functionality I can directly use self okay.
Because we are in the class we use self as this is a node, so we are inheriting from the node.
I can use self dot get logger.
You see it's also working and then.info and I can just use the same log here.
All right.
And that's going to do the same thing.
So this here is doing the same thing as that.
So now I'm going to remove that.
And instead instead of creating a node directly here I'm going to create a my node instance okay.
So from the class my node that I have created with the parentheses.
And that's it.
We don't have any argument here to pass.
All right.
So now I have created the node.
So you see the main is the same.
We still initialize rows to communication.
We create the node.
We make the node spin.
And we have the shutdown.
Now the node is not just using the node class.
It's using our own class which inherits from the node class.
And then we get all of the Ros2 functionalities for the node directly from the class with self dot and
then the functionality.
So let's save this.
And now I can go back here and well let's go back to our Ros2 workspace.
Clear.
Let's do the call code build again.
So let's come back to this command call build with the Python package in this folder.
And then I need to source the workspace.
So once again I can source the bashrc.
I could also close and open a new terminal.
I can just do because here I'm already in this place.
So I can do source install setup bash.
Okay I go inside the install folder and I have the setup bash script.
Great.
So now my workspace is sourced again with all the new changes and I can do Ros2 run my pi pkg with pi
node, which is the executable name.
And no surprise we have the same thing and I press ctrl c and this here what you see here.
That's the template that you can write for any node.
So that's about 20 lines of code.
And in one of the following lessons I will give you the template directly.
You can just copy and paste it if you want okay.
So it's important that you understand how to write this how to build this code.
And then well you don't need to write it every time.
Again you just take this well without the log, but you just take this and you just change the node
name here, maybe the class name.
And that's going to be the same for all your nodes.
And before we continue I want to show you something else here okay.
So we have the node template.
But I want to add one more functionality just to do something a bit more interesting with this node.
Because for now we just print one hello world.
That's not really interesting.
What if we want to, for example, print something every one second?
As long as the node is alive?
That's a very common behavior.
For example, if you create a temperature sensor node and you run to read from the sensor at ten hertz,
so basically ten times per second, how can you do that?
Well, we are going to add what's called a timer.
And the timer functionality is one of the most important ones that you will use in Ros2.
With a timer, you can say, I want to execute this function every x amount of time.
So let's add a timer and to add a timer I'm first going to create a function here inside the class.
So I'm going to add a method named let's say timer callback with self.
And in this timer callback I do self dot get logger.info with hello.
Let's just say hello for now.
I'm going to keep this log here and then I will create.
So in the constructor of the class I will create a timer.
How to create a timer.
Well you can do self.
So you use self always because then you get the functionalities from the node class.
And we can do create timer.
You see we have a create timer function here.
This function will take two parameters.
First is the timer period.
In second that's a float number.
So here let's say 1.0.
So that's one second.
That means we want to call a function every one second.
And the second parameter is the callback.
So we need to provide a callback function.
And the callback function is already implemented here.
That's called timer callback.
So that's going to be self dot timer callback.
And note that we don't provide any parentheses here okay.
If I do this I'm actually calling the function.
If I don't provide the parentheses I'm just giving the reference to the function because we don't want
to call the function.
Now we are just registering the function inside the timer.
And as you can see, so I have named it like that on purpose.
That's actually going to be called a callback function because we call it back later.
All right.
And what's going to happen here?
What's going to happen is that let's look at the main.
So that's what's going to be executed.
We first initialize rows to communication and then we create the node.
So if we create the node we go to the constructor.
We use the parent constructor to initialize the node and give it a name pi test.
Then we print something with the logger functionality.
And then we use a timer.
We create a timer and that's it.
So we don't call this function yet.
We have just created a timer.
But then we are going to do a CLP dot spin with the node.
So spin is going to stop.
The execution here is going to keep this node alive.
And it's going to allow the node to process any callback.
And so here basically with a timer we will have some callbacks.
And because the node is spinning then the timer is saying that every one second we need to call the
timer callback function.
Then because the node is spinning every one second, that function here is going to be called okay.
And that's how this is going to be executed because the node is spinning.
So let's save and then let's go back here.
Let's do build.
And then let's do source.
And then let's do run.
As you can see it's always build source and run.
So remember that you build your source and your run always.
So let's run and you see hello world.
And then you see hello hello hello.
Every one second you can see that with the logs.
Now I press Ctrl C and I stop the execution and I stop the spinning and everything.
All right.
So you see that's quite useful now just for the well for the example, let's just add for example,
we want to say hello zero and then one two, three we could add a counter.
So let's create a counter here.
So self dot counter.
And I'm going to add an underscore here.
So for attributes of the class I'm just going to add a trailing underscore here just as a convention
and let's say zero.
So because the counter is in the class I can use it in that method.
And I can do hello.
Plus as it is an integer I'm going to do str self counter.
And then I can do self dot counter plus one okay.
So I start at zero and then it's going to be 123 etc..
Just one thing I'm going to show you.
Let's say I have forgotten the plus okay.
So I'm going to have an error.
I'm going to have a Python error here.
But let's say I didn't see that.
So I'm going to come back here and let's do the first step, which is to build the package.
Well, as you can see in this case we have a syntax error.
So if we have a syntax error when you build the package here you're going to get an error.
So it's not going to be correctly built.
You see we have errors.
And in this case it's quite explicit.
So I can fix that.
Add the plus save.
Go back and build again.
Okay.
And now it's working.
So with Python, if you have stuff like syntax errors you will see that when you build.
But then of course you know that with Python you can get extra errors.
For example, if you raise exceptions that are not code in your program, then the build is going to
be successful.
But then when you run the program, maybe you will get an error later on.
Okay.
So something to be aware of.
So I have built.
Now I can source and then I can run.
And now you will see hello 0123 etc..
So we could add a space or so if we want to.
But that's, that's about it.
And so with this code you have seen the correct way to create a node with a class okay.
So using object oriented programming.
And you have also discovered a quite important functionality which is a timer that we will use again
and again in this course.