WEBVTT

00:00.050 --> 00:04.880
Let's now improve this node with object oriented programming or OOP.

00:05.180 --> 00:11.240
This will make your node more scalable, and it's the recommended way to write code in Ros2 as per the

00:11.240 --> 00:12.620
official guidelines.

00:12.620 --> 00:17.870
And any way you will see that all the codes well everywhere is using OOP.

00:17.900 --> 00:20.990
So let's create a class here for our node.

00:20.990 --> 00:26.270
And after we have this class, we will have the template that we can use for any nodes that we create

00:26.270 --> 00:27.050
in the future.

00:27.050 --> 00:28.880
So how do we create a class here.

00:28.880 --> 00:35.690
Well I'm going to use the class keyword and let's name it my node.

00:35.930 --> 00:37.820
So here I don't have any context.

00:37.820 --> 00:40.100
So I use my node.

00:40.220 --> 00:45.830
But for example if you would create a temperature sensor node well you would name it temperature sensor

00:45.860 --> 00:46.370
node.

00:46.370 --> 00:51.050
So that's the class that's going to inherit from the node class.

00:51.080 --> 00:52.310
So that's very important.

00:52.310 --> 00:59.900
So you inherit from the node class which means that you will be able to use all the Ros2 node functionality

00:59.930 --> 01:01.100
from our CLP.

01:01.100 --> 01:02.210
So we'll do this.

01:02.210 --> 01:04.480
And then inside we have a def underscore.

01:04.510 --> 01:05.320
Underscore init.

01:05.320 --> 01:09.370
So that's the constructor for Python self.

01:09.400 --> 01:09.640
Okay.

01:09.670 --> 01:12.550
So this is the basic Python OOP stuff.

01:12.550 --> 01:15.610
We create a constructor in this constructor.

01:15.640 --> 01:19.420
The first thing we need to do is super we call the super.

01:20.080 --> 01:23.170
So we call the parent constructor of the node class.

01:23.170 --> 01:27.820
And we do init as well here like that.

01:27.820 --> 01:31.960
And we pass here the node name.

01:31.960 --> 01:35.380
So that's going to be pi test.

01:35.710 --> 01:36.160
All right.

01:36.160 --> 01:41.170
So we call the parent constructor here to initialize the node from the node class.

01:41.170 --> 01:43.600
And that's it for the minimum code for a node.

01:43.630 --> 01:44.050
Okay.

01:44.080 --> 01:48.490
Now I'm also going to add this line here to use the logging functionality.

01:48.490 --> 01:53.740
So how to use the logging functionality I can directly use self okay.

01:53.740 --> 02:01.570
Because we are in the class we use self as this is a node, so we are inheriting from the node.

02:01.570 --> 02:05.380
I can use self dot get logger.

02:05.410 --> 02:13.820
You see it's also working and then.info and I can just use the same log here.

02:14.240 --> 02:14.630
All right.

02:14.630 --> 02:16.040
And that's going to do the same thing.

02:16.040 --> 02:19.340
So this here is doing the same thing as that.

02:19.340 --> 02:22.070
So now I'm going to remove that.

02:22.070 --> 02:31.310
And instead instead of creating a node directly here I'm going to create a my node instance okay.

02:31.340 --> 02:35.360
So from the class my node that I have created with the parentheses.

02:35.360 --> 02:35.960
And that's it.

02:35.990 --> 02:38.180
We don't have any argument here to pass.

02:38.210 --> 02:38.630
All right.

02:38.660 --> 02:40.250
So now I have created the node.

02:40.250 --> 02:42.080
So you see the main is the same.

02:42.200 --> 02:44.900
We still initialize rows to communication.

02:44.900 --> 02:46.040
We create the node.

02:46.040 --> 02:47.270
We make the node spin.

02:47.270 --> 02:48.560
And we have the shutdown.

02:48.590 --> 02:51.650
Now the node is not just using the node class.

02:51.650 --> 02:56.270
It's using our own class which inherits from the node class.

02:56.600 --> 03:03.530
And then we get all of the Ros2 functionalities for the node directly from the class with self dot and

03:03.530 --> 03:04.670
then the functionality.

03:04.670 --> 03:07.070
So let's save this.

03:07.070 --> 03:13.440
And now I can go back here and well let's go back to our Ros2 workspace.

03:13.710 --> 03:14.220
Clear.

03:14.250 --> 03:16.680
Let's do the call code build again.

03:16.680 --> 03:24.000
So let's come back to this command call build with the Python package in this folder.

03:27.660 --> 03:29.850
And then I need to source the workspace.

03:29.850 --> 03:32.250
So once again I can source the bashrc.

03:32.490 --> 03:35.640
I could also close and open a new terminal.

03:35.670 --> 03:39.180
I can just do because here I'm already in this place.

03:39.180 --> 03:42.870
So I can do source install setup bash.

03:43.050 --> 03:48.150
Okay I go inside the install folder and I have the setup bash script.

03:48.780 --> 03:49.020
Great.

03:49.020 --> 04:00.210
So now my workspace is sourced again with all the new changes and I can do Ros2 run my pi pkg with pi

04:00.270 --> 04:03.120
node, which is the executable name.

04:04.020 --> 04:10.800
And no surprise we have the same thing and I press ctrl c and this here what you see here.

04:10.800 --> 04:15.460
That's the template that you can write for any node.

04:15.460 --> 04:17.260
So that's about 20 lines of code.

04:17.260 --> 04:20.650
And in one of the following lessons I will give you the template directly.

04:20.650 --> 04:23.410
You can just copy and paste it if you want okay.

04:23.440 --> 04:28.330
So it's important that you understand how to write this how to build this code.

04:28.330 --> 04:31.000
And then well you don't need to write it every time.

04:31.000 --> 04:37.540
Again you just take this well without the log, but you just take this and you just change the node

04:37.570 --> 04:39.760
name here, maybe the class name.

04:39.760 --> 04:41.890
And that's going to be the same for all your nodes.

04:41.890 --> 04:45.580
And before we continue I want to show you something else here okay.

04:45.610 --> 04:48.430
So we have the node template.

04:48.430 --> 04:54.100
But I want to add one more functionality just to do something a bit more interesting with this node.

04:54.100 --> 04:56.800
Because for now we just print one hello world.

04:56.800 --> 04:58.720
That's not really interesting.

04:58.720 --> 05:03.850
What if we want to, for example, print something every one second?

05:03.880 --> 05:05.680
As long as the node is alive?

05:05.710 --> 05:07.840
That's a very common behavior.

05:07.840 --> 05:13.120
For example, if you create a temperature sensor node and you run to read from the sensor at ten hertz,

05:13.150 --> 05:16.330
so basically ten times per second, how can you do that?

05:16.350 --> 05:19.770
Well, we are going to add what's called a timer.

05:19.770 --> 05:24.600
And the timer functionality is one of the most important ones that you will use in Ros2.

05:24.630 --> 05:30.630
With a timer, you can say, I want to execute this function every x amount of time.

05:30.630 --> 05:37.110
So let's add a timer and to add a timer I'm first going to create a function here inside the class.

05:37.110 --> 05:44.820
So I'm going to add a method named let's say timer callback with self.

05:45.180 --> 05:55.050
And in this timer callback I do self dot get logger.info with hello.

05:55.050 --> 05:56.640
Let's just say hello for now.

05:56.670 --> 06:00.840
I'm going to keep this log here and then I will create.

06:00.840 --> 06:05.580
So in the constructor of the class I will create a timer.

06:05.610 --> 06:07.170
How to create a timer.

06:07.170 --> 06:08.940
Well you can do self.

06:09.570 --> 06:15.330
So you use self always because then you get the functionalities from the node class.

06:15.330 --> 06:18.900
And we can do create timer.

06:18.900 --> 06:21.070
You see we have a create timer function here.

06:21.100 --> 06:23.860
This function will take two parameters.

06:23.860 --> 06:26.770
First is the timer period.

06:26.770 --> 06:29.230
In second that's a float number.

06:29.230 --> 06:32.560
So here let's say 1.0.

06:32.560 --> 06:33.880
So that's one second.

06:33.910 --> 06:39.100
That means we want to call a function every one second.

06:39.130 --> 06:43.510
And the second parameter is the callback.

06:43.540 --> 06:46.210
So we need to provide a callback function.

06:46.210 --> 06:48.700
And the callback function is already implemented here.

06:48.700 --> 06:50.980
That's called timer callback.

06:50.980 --> 06:57.340
So that's going to be self dot timer callback.

06:57.670 --> 07:01.690
And note that we don't provide any parentheses here okay.

07:01.720 --> 07:05.140
If I do this I'm actually calling the function.

07:05.170 --> 07:10.450
If I don't provide the parentheses I'm just giving the reference to the function because we don't want

07:10.450 --> 07:11.320
to call the function.

07:11.320 --> 07:15.670
Now we are just registering the function inside the timer.

07:15.670 --> 07:18.940
And as you can see, so I have named it like that on purpose.

07:18.940 --> 07:24.840
That's actually going to be called a callback function because we call it back later.

07:24.870 --> 07:25.350
All right.

07:25.350 --> 07:26.910
And what's going to happen here?

07:26.970 --> 07:29.730
What's going to happen is that let's look at the main.

07:29.730 --> 07:31.800
So that's what's going to be executed.

07:31.950 --> 07:35.760
We first initialize rows to communication and then we create the node.

07:35.760 --> 07:38.400
So if we create the node we go to the constructor.

07:38.580 --> 07:44.310
We use the parent constructor to initialize the node and give it a name pi test.

07:44.340 --> 07:47.520
Then we print something with the logger functionality.

07:47.520 --> 07:49.500
And then we use a timer.

07:49.500 --> 07:51.330
We create a timer and that's it.

07:51.330 --> 07:52.890
So we don't call this function yet.

07:52.920 --> 07:54.330
We have just created a timer.

07:54.330 --> 07:58.410
But then we are going to do a CLP dot spin with the node.

07:58.410 --> 08:00.480
So spin is going to stop.

08:00.480 --> 08:04.440
The execution here is going to keep this node alive.

08:04.440 --> 08:08.460
And it's going to allow the node to process any callback.

08:08.490 --> 08:12.630
And so here basically with a timer we will have some callbacks.

08:12.660 --> 08:18.390
And because the node is spinning then the timer is saying that every one second we need to call the

08:18.390 --> 08:20.280
timer callback function.

08:20.280 --> 08:25.800
Then because the node is spinning every one second, that function here is going to be called okay.

08:25.830 --> 08:30.640
And that's how this is going to be executed because the node is spinning.

08:30.640 --> 08:34.210
So let's save and then let's go back here.

08:34.990 --> 08:37.720
Let's do build.

08:40.720 --> 08:42.670
And then let's do source.

08:43.270 --> 08:44.890
And then let's do run.

08:44.890 --> 08:48.040
As you can see it's always build source and run.

08:48.040 --> 08:52.450
So remember that you build your source and your run always.

08:52.450 --> 08:55.900
So let's run and you see hello world.

08:55.900 --> 08:57.940
And then you see hello hello hello.

08:57.940 --> 09:00.910
Every one second you can see that with the logs.

09:00.940 --> 09:06.040
Now I press Ctrl C and I stop the execution and I stop the spinning and everything.

09:06.070 --> 09:06.670
All right.

09:06.670 --> 09:12.370
So you see that's quite useful now just for the well for the example, let's just add for example,

09:12.370 --> 09:17.980
we want to say hello zero and then one two, three we could add a counter.

09:17.980 --> 09:20.860
So let's create a counter here.

09:20.890 --> 09:24.070
So self dot counter.

09:24.220 --> 09:25.960
And I'm going to add an underscore here.

09:25.960 --> 09:32.280
So for attributes of the class I'm just going to add a trailing underscore here just as a convention

09:32.430 --> 09:34.050
and let's say zero.

09:34.050 --> 09:37.740
So because the counter is in the class I can use it in that method.

09:37.740 --> 09:39.180
And I can do hello.

09:40.320 --> 09:46.740
Plus as it is an integer I'm going to do str self counter.

09:47.700 --> 09:53.430
And then I can do self dot counter plus one okay.

09:53.430 --> 09:56.820
So I start at zero and then it's going to be 123 etc..

09:56.850 --> 09:58.380
Just one thing I'm going to show you.

09:58.410 --> 10:00.660
Let's say I have forgotten the plus okay.

10:00.660 --> 10:02.220
So I'm going to have an error.

10:02.250 --> 10:03.840
I'm going to have a Python error here.

10:03.840 --> 10:05.700
But let's say I didn't see that.

10:05.970 --> 10:14.520
So I'm going to come back here and let's do the first step, which is to build the package.

10:15.840 --> 10:19.860
Well, as you can see in this case we have a syntax error.

10:19.860 --> 10:25.380
So if we have a syntax error when you build the package here you're going to get an error.

10:25.380 --> 10:28.140
So it's not going to be correctly built.

10:28.140 --> 10:29.580
You see we have errors.

10:29.610 --> 10:31.800
And in this case it's quite explicit.

10:31.800 --> 10:33.670
So I can fix that.

10:33.700 --> 10:36.280
Add the plus save.

10:36.340 --> 10:40.270
Go back and build again.

10:41.740 --> 10:42.190
Okay.

10:42.220 --> 10:43.180
And now it's working.

10:43.180 --> 10:47.620
So with Python, if you have stuff like syntax errors you will see that when you build.

10:47.620 --> 10:51.310
But then of course you know that with Python you can get extra errors.

10:51.310 --> 10:57.100
For example, if you raise exceptions that are not code in your program, then the build is going to

10:57.100 --> 10:57.730
be successful.

10:57.730 --> 11:01.150
But then when you run the program, maybe you will get an error later on.

11:01.180 --> 11:01.360
Okay.

11:01.390 --> 11:03.100
So something to be aware of.

11:03.370 --> 11:04.360
So I have built.

11:04.390 --> 11:07.810
Now I can source and then I can run.

11:08.740 --> 11:14.410
And now you will see hello 0123 etc..

11:14.410 --> 11:16.660
So we could add a space or so if we want to.

11:16.690 --> 11:19.000
But that's, that's about it.

11:19.000 --> 11:25.420
And so with this code you have seen the correct way to create a node with a class okay.

11:25.450 --> 11:27.580
So using object oriented programming.

11:27.580 --> 11:34.000
And you have also discovered a quite important functionality which is a timer that we will use again

11:34.000 --> 11:35.920
and again in this course.
