# ros2_control with ROS2 [1h20 Crash Course]

## Метаданные

- **Канал:** Robotics Back-End
- **YouTube:** https://www.youtube.com/watch?v=B9SbYjQSBY8
- **Источник:** https://ekstraktznaniy.ru/video/39300

## Транскрипт

### Segment 1 (00:00 - 05:00) []

Hey everyone and welcome to this crash course on Rossto control. If you want to work with Ross 2 and real hardware, you will need to use ROS2 control at some point and maybe you have already started to learn it but you feel completely lost. Well, I would say this is quite normal and you have come to the right place. Note that this is not a tutorial for complete beginners. You need to actually have some Rosto basics already so you can clearly understand this. Now what will we do in this crash course? We will start with a quick ROST to control overview and then we will dive directly into the code to set up a ROST to control stack for a mobile robot. I will give you the URDF for the robot as a starting point. To set up this roster control stack, we will use a mock component which makes it easier to begin. This crash course is great to get started and understand Rosto control. And if you want to go further and create your own custom hardware driver, hardware interface and controller, then I have a much bigger course for you which contains 7 hour of video content, lots of practice and projects and downloadable code templates that you can use for your own projects. You can find the course link in the description below. All right, and now let's get started with the crash course. First step, let's understand how ROS control works with a global overview. So let's start with this on the left here. You see we have our application. So what's the application? It's for example an application like navigation stack that's going to give you a common velocity for a robot to move in a room or you can have an application that's going to control a robotic arm. Well, that's kind of the higher level application in ROSS that's going to tell your robot what to do but not how to do it. Okay. So we have this we have the application on the right side here I have my hardware so it's a brown box it's just the hardware the piece of hardware so it can be a motor sensor or a combination of motors and sensors well that's the hardware for our robotic system now well there's a lot of things missing in the middle so how do we pass the command from the application to the hardware and let's actually start not from the application but start from the right side from the hardware and first we will need to add a hardware driver. So here, this has nothing to do with ROSS really. It's just a piece of code like a Python, C++ code that's going to allow your computer to talk to the hardware. So for example, you need to start uh communication with the hardware using a certain protocol like serial, I2C, canvas, etc. You're going to also have some functions so that you can correctly kind of translate a command into something that the hardware can understand. Okay, so hardware driver is something that's not really specific to ROSS. It's something you would do for any piece of hardware. And then here we have ROSS to control. Okay, between the application and the hardware driver. What do we have inside ROS to control? We have two things. So still going from the right side, we have the hardware interface. So the hardware interface is the well as the name suggests is the interface to the hardware. So it's going to be directly communicating with the hardware driver. Sometimes those two are kind of mixed together and are the same thing. But we're going to also see later how it's best to have a pure, let's say pure C++ hardware driver and then a hardware interface that's going to work with it. So hardware interface is basically also just communicating with the hardware. It's a piece of code inside your ROS to control architecture that's going to allow you to send commands to the hardware and to also read the data from sensors of our encoders or stuff like that. And then to complete this, we have the controller inside ROS to control. And so the controller is going to take a command from the application and it's going to do for example interpolation. It's going to make sure that the command is running smooth maybe uh with smooth accelerations, velocity, all that stuff. So this all the stuff you can decide. You can create your own controller and you can also use existing controllers. So there are a lot of existing controllers. We're going to see uh for example to control the differential drive robot, the robotic arm etc. So now the global overview is kind of finished. Okay. Inside roster control you have the controller which is taking the command from the application and saying how uh the command should be outputed to the hardware. But the controller doesn't talk directly to the hardware. So it's going to send that to the hardware interface and then hardware interface is going to talk to the hardware and also send the feedback to the controller. Now what you might see if you go to ROS2 control documentation uh and stuff like that you might see something like this with actually we don't necessarily have one controller and one hardware interface. We can have many controllers and many hardware interfaces. So if you have a complex robotic system with for example a mobile base, a robotic arm, some sensors, maybe even a simulation here and there, well you can do all of that with ROS to control. You can have

### Segment 2 (05:00 - 10:00) [5:00]

many controllers that communicate with different hardware interfaces which uh are also communicating with different hardware drivers. Okay, so ROS to control is very modular, very scalable. You can do lots of thing with it. But to get started, let's actually come back to this which is already complex enough and let's try to understand this first. Now to understand this ROS 2 control box, I'm just going to zoom in. We have as I told you, we have a controller and we have a hardware interface. How this is going to be connected together is we're going to have also in roto control what we call the controller manager. Okay, so you're going to have your controller, which is either something that you write yourself or you get an existing controller. Then you have your hardware interface and you're going to start everything with the controller manager. It's going to take those two and then you can say you want to bind the controller with this hardware interface and the controller manager is going to do all of that for you. Okay, so in the end what we need to do with roster control is we need to provide a controller. hardware interface and then with the controller manager we can start everything. So coming back here that's everything we need to do to adapt the robot to ROS to control. I'm going to give you an example with some units. Okay, because it might still be a bit confusing. So let's say that the application is a navigation for a mobile base and the application is sending a common velocity topic. So we have a common velocity topic with a let's say a twist message. You might already know this message and it's going to send a linear or angular velocity in meter per second and radian per second for the robot. So for example going forward with a speed and then turning left or right with a certain speed. Okay, this is specific to the robot. Then the controller is going to transform that velocity but for a velocity for each wheel. So the controller is aware of the dimensions of the robot, how many wheels we have. So do we have one wheel, two wheels, 14 wheels? It's going to take the command from the application and say each wheel at specific time must run at x region per second. Okay, so here we are already in the how and we already specific to the robot. But still at the controller level, we don't know what hardware we're talking about. we just know it's specific to the wheels for that robot but we don't know the hardware. Then we're going to send that command to the hardware interface and this is going to be the connection between the well the controller and the driver is going to transform that command from so for each wheel into something that the motor can understand. So for example, an RPM, so rotation per minute, and then it's going to use a certain communication protocol to send that to the motor. And when we go back, it's also going to read an RPM that's going to be transformed into, for example, a region per second that's going to be sent to the hardware interface. And then the hardware interface is going to send back to the controller and the controller can do kind of a closed loop control to send the next command. Okay, so with this you can kind of see that each layer is only handling one thing and the more we go right the more we are specific to towards the hardware and the more we go left the more we are just global about the application. Now you can see we need to well we need to specify controller hardware interface and hardware driver that's a lot of things and to start with ROS to control what we can do is we can just use a mock component. So a mock component is a fake and perfect hardware and it's useful to get started. Basically we can skip the whole hardware interface hardware driver. We don't even need the hardware. We just need to set up a mock component that's already existing within ROS to control and thus we can test our ROS to control architecture with a controller the mock component and we can start everything. And note that when I say it's a fake and perfect hardware you could think that it's kind of a simulation. So yes, somehow it's a simulation, but it's a perfect simulation. It's not a real simulation like gazebo where you have physical constraints, gravity, etc. Okay, this is just a short circuit before the hardware so we can develop our RO2 control stack one step at a time. I will do a quick recap of what we need to be able to run and work with ROSTU and we are going to install the packages for Rosto control. So I will go quite quickly because you should already know how to work with ROSTU. Those are the prerequisites for this course. So first of all we need YUbuntu. Here I have YUbuntu 24. 04 and I recommend that you have at least this version or a more recent one. I have installed it. Uh so this is the native installation with a dual boot. Okay. It's probably much better to have that than to have a virtual machine. Then you will need to install ROS 2. So the corresponding ROS2 version or Ubuntu 24 that's ROS to jazz. But if you have another Ubuntu version then install the corresponding RO2 distribution. And so

### Segment 3 (10:00 - 15:00) [10:00]

for Ros2 Jazzy I have documentation here. You just follow the Ubuntu dev packages page on the documentation. Okay. You're going to well you might need to set up the locale enable some repositories set up the sources here. Install the development tools then update upgrades and you just install here. I have installed Ross desktop. All right. So that's what we need. And then for the environment, you see we need to source this setup. bash script. And I have already put that into my bash rc at the end. You see what you can ignore this commented line, but I have already the line to source the setup. bash script so that we can use ROS2 in all the terminals. Great. So that's it for the ROS2 installation. And now we are going to install the packages for ROSS to control. So sudo apt install Ross and then the distribution. So from JZ and then you have Ross to control. We are going to install this one and then ROSS distribution ROS to controlless. So okay. So we are going to install ROS to control and ROS to controllers. Press enter and well I've already done that but for you it's going to install a few new packages and that's it about the ROS two packages we need. As you may already know the URDF is one of the first things you need to have for a robot to work with ROSS. In the URDF, you describe the different properties of the robot, mainly the links, which are all the independent rigid parts and the joints which represent the connection between those links. Now, to set up ROS to control for a robot, well, you will need a URDF first. As URDF is a prerequisite for this course and as I want to keep this course focused on roster control, I'm giving you directly a package with a URDF for a mobile base. So you can download here section two starting code and we're going to extract and you can see inside we have my robot description package. Okay. So what I'm going to do is well I'm going to go back to my home directory. Let's do that from the terminal and we are going to create a workspace. So for example ROS2 workspace. Okay. And in this, so let's go to the ROS to workspace and we create a source folder. Okay, we have a workspace. So this you already know. Now what I'm going to do is take this my robot description package. I'm going to copy and paste it inside the source folder here. Okay, if I do ls uh if I go to the source, I have my robot description package. Okay, so you create a workspace and you put the package here in the source folder of the workspace. We're going to go back and before we check the code, let's just see what we have. Uh let's just build it called com build. Then we're going to source the install setup bash which we can also put inside. So let's open the bash SC at the end. Uh okay, I already had this commented. So you have the line to source the global rest to installation and then the line to source your workspace. As usual, we save the bash rc. Okay, you make sure that you have source. So you open new terminal or you s the script bash rc and then we can do I'm just going to do cd. We can do ROS to launch my robot description. You should use the autocomp completion here. You see if it works then means that the build was successful. And then we have display. launch dot and then XML. There's a Python version as well. We're going to start the XML. It doesn't matter. You start this. Okay. And this is going to start RV. And you see our robot. So it starts ARV and also a joint state publisher window. Okay, we can put that side by side. And what you see here is we have a mobile base. That's what we're going to use as a starting point. So we have a baselink here, two wheels and a caster wheel. Okay, very classic stuff. And then you see we have two joints. So revolute joint actually continuous joint here for the right wheel and the left wheel. All right. So, this is quite classic. It should not be really new to you. Okay. So, what we have is basically uh uldf that's configured also with the

### Segment 4 (15:00 - 20:00) [15:00]

TF and that's going to be the starting point for any of your uh ROST application. Now, let's have a look at the code. I'm going to uh stop that here. Let's go to the workspace and I'm going to open. So, as usual, I go to the source folder of the workspace and I do code dot Okay, that's the best way to start the workspace here. And in my robot description, what do I have? Well, we have a package. xml, the cm list. txt. And you see here we have three more folders. Launch RV and URLF that I installed here with inside the cate. txt with the install function. Okay, in the URDF we have so the main file is my robot. df. zacro which includes common properties and mobile base. Okay, we're going to use zacro here. In common properties I have what material uh blue and gray. So we have some material tags. So not much is just for the colors that you see on our and then on mobile base we have what? Well, first we have properties with the dimensions, okay, for the base, the wheel, etc. And then we have all the links and all the joints. Okay, that's it. You see, we have the base footprint and then the base link. Uh we have a macro for the wheel. So then we have the right and the left wheel and the caster wheel. Then we have the joints. Okay, between the base footprint, the base link and then between each of the wheel. So the right, left and caster wheel. All right. So that's the URL part. Then we have also the RV config so that when we start avis we can start with the view already like it was. And then in the display that launch. So either the Python one or the XML one. It's the same. I'm going to use the XML. It's much easier. You see what do we have for now here? I have variables to find the URF path and the config path. But basically we start what we start the robot state publisher. Okay. It's basically the first node you're going to start in ROS application robot state publisher and you provide the URDF. Then we have a joint state publisher GUI. So graphical this is just to visualize the movement of the joint states. Okay, we're going to have to do that also later by ourself. And we start a okay so this launch file is not the launch file we're going to use for our application is just the launch file to display the URL. Okay. And so that's uh basically the starting point. In this lesson, we are going to do the first step to adapt uh the robot to ROS to control. We are going to add a ROS to control tag in the URDF. So let's uh go back to our workspace. Let's open it here with VS Code. And well you have the URDF here with as you see a main Zacro file that includes the common properties here and all the links and the joints for the mobile base. So I have named my robot mobile base. Okay. So this part of the robot is named mobile base. Here we are going to add a ROS2 control tag. But actually I'm not going to add it directly inside this zero file. I'm going to create a new one. So let's Let's name it mobile baseu_control dot zacro. Okay, this is something that's quite common to do. And then that's a zacro file. So I'm going to start with I'm just going to take from any other file. I'm going to start with the XML tag and the robot tag with the zacro here URL. I'm just going to take that and close the robot tag. Okay, let's save. We have a Zacro file and before I write anything here, we're going to use it in our main Zacro file. So, I simply need to do a Zacro include and then file name that's going to be mobile base to control dot zero. Make sure you don't make any typo here. And let's save this file. Okay. So, in the main file, we include all those three files. Great. So, that's a great way to separate our code and make it cleaner. Now, let's start this ROS to control tag. So, going to add a tag that's simply ROS2 control. And I need to give a name. So, for the name, I'm going to use mobile base. Okay. and then hardware interface. This name is not really important for now. You can just uh put the name of the robot or the system

### Segment 5 (20:00 - 25:00) [20:00]

inside your robot and then hardware interface. Okay, as a convention. And then we need to provide a type. So type can be sensor, actuator or system. So what does it mean is if you're going to control just one sensor that you're going to read data from, you can use sensor. If you control just one actuator, like just one motor with this interface, you can use this. But if you control multiple joints or multiple sensors or multiple well more than one thing from the same hardware interface, you're going to use system. You don't need to worry about that for now. Just use system for everything because system includes sensor and actuator. So don't worry about this. Just use system. You open and you close ROS two control. All right. Then we need to add a hardware tag. We open and close the In this hardware tag, we're going to use a plugin. And what's inside this plug-in? So, I'm going to first close. We need to provide the hardware interface. So if you remember what we saw before is that you have a controller in RO to control and you have a hardware interface. Well, after you develop a hardware interface, you're going to be able to put the name of the hardware interface here, but we haven't developed a hardware interface yet. We're going to use a mock component. So we're going to write mock components like this with an S slash generic system exactly like this. Okay. So this is lower case with an underscore and this is camel case upper camel case. If we use this plug-in well it's something you cannot really guess but you need to also use param name. We can put some we can give some parameters to the interface. That's going to be calculate dynamics and uh value is true. Okay. So it's not so much to understand now. you just know that you have to write this and this is going to be the same for any robot. So once you just know how to write the ROS to control tag it's going to be the same you give a name a type we use system by default and then for the hardware interface you just use mock components to start and after this we need to provide the interface for each joint that we will want to control with ROS to control. Okay. So those joints are going to be passed to uh the controller. So I'm going to add the joint here. Make sure that the hardware and the joints are separate. Okay. The joint is now inside the hardware. And then name and that's going to be the exact name of the joint that we have in the URF. So for this I'm going to go back here and to the joint base right wheel joint. Okay. So I can start with the right or the left wheel which is the same. Let's go here. Okay. I open and close. And in this I will need to specify tags such as comment interface name. So what is this? Well, in this roster control tag, you're going to set what kind of hardware interface you use, which for now is a mock component. And then you're going to specify common and state interfaces for each joint that you will want to control. And that's going to be passed to the controller. Okay, so it's kind of a UDF configuration that's going to be passed to the controller to see well what kind of common interfaces. And here you can basically write position, velocity, um I think acceleration maybe and also torque or effort. So how you're going to control the joint? Okay, because this is a wheel, we're going to give a velocity. So I write velocity. So basically what command you want to send to that joint, position, velocity, something else here, it's velocity. And then we also have state interface. What uh data we're going to read from the joint. And here I'm going to also put velocity. So if you wanted to do an open loop control and the controller is only open loop, you could just send the command and not have any state. Here it's going to be a closed loop control. So, the controller we're going to use, we're going to see that in the next lesson, is going to need to send a velocity command and receive a velocity state. And actually, I'm going to add another one here. State interface name position because for the controller to work, we uh so that's specific to this controller for the differential drive, it's going to also need to know the position of the wheel. So, we're going to send velocity

### Segment 6 (25:00 - 30:00) [25:00]

and we're going to read position and velocity. We're going to do the same thing for the So, this is the right wheel. We're going to do the same thing for the left wheel. And because those are going to be the same, I'm just going to copy the joint tag and paste it here. And replace that with the name of the joint for the left wheel like this. And that's going to be it for the ROS two control tag. So to recap, you give a name. It's not so important for now. System for the type. You set the hardware interface, which for now is a mock component. And then for each joint, you put the name of the joint and what kind of command you want to give state you're going to receive from that. Now that you have added a ROS to control tag inside your UDF, we're going to do the second step here, which is to add a controller config. Okay. to specify which controllers you want to use and set different parameters for those controllers. All right. And with this we would have the complete RO2 control setup with one side the controller and the other side the hardware interface specified here. And once again if things don't make sense for now well it's definitely okay. It's normal. The thing is when you learn roster control there's a lot of stuff that you need to start by just well using what's existing using what works not necessarily understanding it but then as you progress and then you come back to the big picture then you will put all the pieces together okay so just follow along we're going to make this work and you're going to understand better as we progress so how do we specify a controller configuration well for now we only have one package my robot description okay in this package we have the URDF and also well the ROS to control tag because that should be in the URF. Now we're going to add a config file. So what I'm going to do is I'm going to create a new package. So I'm going to come back to a terminal. Let's go to Rosto workspace and source and I'm going to create a package with Ros2 pkg create my robot. So the name of your robot and then bring up. Okay. So you've already done that to create launch files and also uh YAML files. That's what we're going to do right here. So we create our bring up package. Maybe you already have one. Then use this one. Okay. So I just do a ROS2PG create and then I'm going to go inside my robot bring up. And what do I have here? Well, I'm going to keep the ccklist. xt and keep the package. xml, XML, but I don't need include and source. So, let's remove those. Remove include and source. And I'm going to add a config folder. Okay, the launch folder later. Let's do things one step at a time. So, let's go back to our VS Code here, my robot bringup. I have my config folder. And then what I'm going to do in the cm list. txt, txt. I'm going to clean this a bit so I don't need the build testing and those comments and I'm going to add the instruction to install. So install that's going to be directory um config and then destination that's going to be share slash and then dollar sign curly brackets project name which project name is basically the you see the name of the package. Uh I can add a slash if I want to. All right. So just install the config folder inside the share repository here for this package. I'm going to save that and that's it. Okay. So this should not be new for you. You probably done that already several times. Now in my config folder, I'm going to create a new file and well I'm going to name it my robot controllers. Yamel. Press enter. Okay. So that's going to be a YAML config file and you can name it as you want here just something controllers. So here it's for my robot. So the name of the robot is my robot. So I just name it like this. And then the first thing that we're going to do is we're going to add parameters for a node called controller manager. Okay. Okay, so if you remember in the introduction of this section, I have introduced the controller manager to say that this controller manager is going to kind of start the different controllers and bind them with the hardware interfaces. And we need to specify some parameters. So I put ROSS and then double parameters. The first parameter that we're going to need is update rate. And that's one of the most important. So basically your controllers, what are they going to do? They're going to read something from the

### Segment 7 (30:00 - 35:00) [30:00]

feedback or read something from the command that's being passed from the application. Then they're going to update the next command and they're going to write the command uh to send to the hardware. Okay, so basically it's a loop of read update write. And I'm going to come back to this later. And so how often do we update the controllers? So if I put 10 here, that's going to be an integer. It means 10 hertz. So 10 times per second. So depends on the application. This might be enough or quite slow. I'm going to put 50. Okay, 50 times per second. In some applications, like if you have a robotic arm and you need a real almost like realtime constraint, sometimes it goes up to 500 or 1,000, even sometime 1. 5 kHz I've seen. So well that's going to depend on your application, but to start something like 50 100 is going to be enough. And after this, so well, we have only one parameter for the controller manager, but we're going to add more parameters which correspond to the different controllers we want to start. Now, you might ask, uh, what controllers? Well, where are the controllers? And that's a very good question because, uh, the documentation actually doesn't really exist at the time of recording this course. Uh, what you have to do is you have to go to GitHub. Uh, so you can easily find this. Okay, Ross 2. You just type ROSS2 controllers on Google. You just find this under the ROS controls um GitHub repository. And what you can find here is uh different folders and all those folders here they are all existing controllers that you can use. Okay? And those are going to be very useful. And so I'm going to show you which one we're going to use now and also how to be able to use them by actually reading the necessary code inside those folders. Okay, that's the documentation that you're going to use. So it's not optimal, but actually it's not that bad once you understand just how to use it. And so you can see we have uh we're going to use a diff drive controller because we have a div drive robot. Uh you have stuff like four stock sensor broadcaster. You see gripper controller, GPIO controller, you have tricycle controller. Okay, you have lots of different things. Velicity controllers. So, we're going to use a few in this course and then of course you can use more. Those controllers that you see here, they are working quite well and they are actually enough for most use cases in robotics. And the first controller that we're going to use is the joint state broadcaster. So, what broadcaster? Well, it's going to publish the joint states for each of your joints here. So, the left wheel and the right wheel that we have. And now you might think, well, why do we need that? Well, because actually nothing is going to publish the joint states if you don't do it or don't specify uh to do it through a controller. Because if you look at what we have um in our my robot description in the launch in the display launch XML where we have started to just display the robot is we have started the robot state publisher. The robot state publisher is going to listen to the join state so that it can publish on the TF. Okay. So something somebody needs to publish the join state. What we have done here in this example is just to use a fake join state publisher with a graphical interface. So we can well fake the join state. But we don't want to fake the join state for a real robot or real project with roster control. So we need something that's going to get the data from the hardware and publish it on the joint state topic. Okay. And that's where the joint state broadcaster uh comes in. And note that well this is a controller but a controller doesn't necessarily mean that you're going to control a hardware in the way of for example moving a motor. Okay, controller can just be something that's going to read uh some data from the hardware and publish that on a topic. Okay, that's also a controller. And so we're going to use the joint state broadcaster. Actually, you're going to use it probably in all your projects because as soon as you have joints in your URF, basically you're going to want to publish the joint states for those. So, you're going to have the joint state broadcaster. So, what we do here, you can copy paste in basically all your projects. All right. How do we use this? Well, uh you go to the joint state broadcaster folder here in the package and you see we have a XML here. We have a plug-in join state plug-in. xml. You're going to click here and you see some kind of well XML file here. We're going to use something similar when we create a hardware interface, okay? Later in this course, but for now, let's just keep things simple. You see, we have joint state broadcaster and we have a class with a name and a type. You're going to use the name, okay? The the thing with the slash here. So, joint state broadcaster slash joint state broadcaster. That's going to be what we're going to use in our file. So, we

### Segment 8 (35:00 - 40:00) [35:00]

go back. Uh, I need to name it. I need to give it a name here. I'm just going to name it joint state broadcaster. Okay, that's this is the name that we're going to use when we start it here from the launch file. So, you can name it ABC if you want. You just need to use ABC later in your launch file, but we're going to use something that makes sense. And then so I'm going to actually go back to a new line, new indentation. I'm going to put type and for the type I'm going to use the name of the class here from this XML file. Okay. So I copy this and I put it right here. Okay. So make sure that you put the name. So the name that you create for the controller also under the parameters of the controller manager here. So it can be started. And then under the name that you choose, you put type and then you write the type here. Okay. Then for a control you can also specify some parameters. So if we go back here then you go to the source folder. In the source folder you have the CPB file but you also have a YAML file. In this YAML file you have all the different parameters you can use with the type, the default value, description, etc. So I'm not going to go through all of them. just show you the joints. Okay, so the joints is a string array with a empty uh array by default. Okay, and you can see that if uh it's left empty, all available state interfaces will be published. Okay, I'm coming back here. What are the state interfaces is going to be if I go back to the URF and the ROS to control tag state interface. Basically, we're going to have the position and the velocity for each joint. Okay? And by not providing this parameter, we're going to publish all the joint, which is well, which is what we're going to do for now. We might change that later, but for now, we're just going to not write this parameter. Okay? So, I'm not going to use any parameter for this joint state broadcaster. Uh, we're going to use parameters for the next controller that I'm going to do now. So, you can see how to add them. You have already made a lot of progress. Congratulations. Now we are about halfway through the crash course. I hope that you are learning a lot and I also hope you like the course. If you find it useful, then you might want to check out my bigger ROS control course which contains more than 7 hours of structured video lessons and which will take you much further into the understanding of Rosto control. The course will also teach you how to create your own hardware interface so you can bridge ROT control with your real hardware. Well, I will leave a link in the description if you are interested. All right, and let's continue with the video. Now, let's add a second controller. Okay, I'm going to name it. So, I just go back to a new line here, still under the parameters for the controller manager, and I'm going to name it div drive controller. Okay, I just name it as I want. I just make sure that I give a name that has a sense um and then type. What's going to be the type? Well, we're going to go back here, go back to our ROS two controllers, and we're going to use the diff drive controller. Okay, this one is a quite common one, and you can probably find lots of examples online with different configurations for that. So, we go here. You see we have a XML plug-in file, which is the same as the other one. and you have div drive controller here with a slash that's the class name that we're going to take and put right here. Okay. So now when you see a file like this you understand how it's made. And then I'm going to go back here and to the div drive controller to the source folder. We have more files but we're going to only open the YAML file which contains all the possible parameters and those are you can see we have more parameters and this time we're going to specify a few of them okay because some are really important now how to specify the parameters well what I'm going to do simply is I'm going to go back to a new line here so after controller manager and I'm going to put the name here div drive controller so the name I've created here even if it's the same name as you see this kind of name space those are not the same thing okay it could be any different name so I put D drive controller and then two spaces ROSS parameters and we're going to add the parameters for this controller here okay so basically when you start this the joint state broadcaster is going to be a node the div drive controller and you just put the parameters for that note.

### Segment 9 (40:00 - 45:00) [40:00]

Now, what parameters are we going to use here? Well, let's go uh step by step from the beginning. You see, we have left wheel names, okay, in plural, and that's a string array because for a div drive robot, well, in this case, we just have one left wheel and one right wheel. But you could have two wheels on each side and still have a differential drive robot. Okay? If both wheels are turning at the same time, then the robot can work exactly the same. You can have two wheels, three wheels, six, as many as you want. So, we need to add the left wheel names and put an array with the joints that correspond to the left side. And you see the default value is empty. So, if we don't specify this, it's simply not going to work. So, I'm going to go here, left wheel names. That's going to be an array here. and with quotes. I'm going to add the joint for the left wheel. So, I go back to the uh URF here, mobile base, and you see base. So, make sure not to confuse left and right base, left wheel joint. I take the name and I put it right here. Okay. And we would have the same right wheel names with this time is going to be base right wheel joint. Okay. So this is because I have named it like this. But of course in your robot if you have used a different name you use the name you used in the URF. Okay. So the first very important thing is what are the joints that we need to control. Okay. So where are the wheels? Because this controller is going to control the wheels. It needs to know what it needs to control. We go back here. Then we have two more parameters. Wheel separation and uh well wheels per side. So well wheels per side actually we don't really need it zero. But uh if you have more than one wheel per side, you probably need to set this one. But we're going to use wheel separation and wheel radius. Okay, those are really important values. You see set to zero. So we need to provide that. So I'm going to put wheel separation and wheel radius. Now what is the wheel separation? I'm going to go back here to the mobile base and let's see what we have. So you could start this. You could start the display launch XML to see it again. Okay. Um basically the wheels are on each side of the base link and the base link we have the base width which is 0. 4. Okay. And then the wheels are on the outside. Okay. So the wheel length is 0. 05. Meaning that the actually the joint for the wheel on each side is half of this from the base. So 0. 025 on each side. Which means that the total distance between the two joints is 0. 025 multiply by two which is 0. 05 plus 0. 4. Okay. If you don't understand this, I encourage you just start the RVs with the display launch XML and visualize it for yourself. And so wheel separation, we have 0. 45 cm. This is very important. If you are wrong with this value, well, it's still going to work, but the velocity output is not going to be correct. And then the wheel radius, this one is easy because we already have wheel radius here, 0. 1. Okay, it's the same thing. Then I go back here and what else do we have? Well, we're not going to use the wheel separation multiplier and all that stuff. I'm going to go down here and I'm going to specify the ODOM frame ID and the base frame ID. So I'm going to put ODOM frame ID and base frame ID. Why do I do this? Because well the diff drive controller is going to do actually two things. First it's going to control the wheels. Okay? So, it's going to receive a common velocity and it's going to output that to basically a common velocity for each of the wheels. So, it's going to send a velocity and receive a velocity back to create a closed loop control. Okay. Now, if I go back to the interface, that's why we have a command interface velocity and a state interface uh sorry, this one state interface velocity. Okay. But it's also going to do a second thing which is to publish the autometry. What is the autoometry? The autoometry is simply the well the distance between the point where you started the robot and where the robot is right now. So it's going to actually publish a new TF which we call

### Segment 10 (45:00 - 50:00) [45:00]

ODOM for autoometric and to publish this TF. So I think is that I have not read the code entirely of for the controller but I think it that's why it needs to have the position so the state interface position that we have specified here to actually compute the autotry. Okay. So the basically the command interfaces and the state interfaces we have specified are kind of specific also to the controller that you're going to use. And I know this is a bit of black magic but well that's just how it is. How do you know that? Well, it's just with experience that you know that. So, now that I told you, well, for the next time, you know it. All right. And so, this is going to publish a nitional TF. Now, you might also think, well, that's a bit weird because we're going to basically have a joint state broadcaster controller that's going to publish the joints for those two uh wheels here. And then the robot state publisher is going to listen to those joint states and publish the TF. And here we are publishing another TF. And yes, that's not a problem. You don't necessarily need to publish all the TFS from the same node from the same place. Okay, you can have the TF or the joints of the robot published through the robot state publisher, but you can also publish from anywhere from this controller. You can publish an additional TF. That's not going to be a problem. So here we publish the ODOM to base. So what is going to be the TF? The first one named ODOM. That's a new frame. And ODOM to what? Actually here it's not ODOM to base link. It's ODOM to base footprint. Okay, because we have defined a base footprint link for the robot. If I go back to the parameters, you see the default one is ODOM. Okay, so we're going to keep the same. I'm still going to provide it. And then base link. Okay, so if I keep this, that's not going to be correct. I need to change to base footprint. So I'm going to go back here and say autumn. So ODM is a string base footprint. Okay, this one is very important. And even if this one by default is ODOM, sometimes also better to just still provide the parameters. So in case later you can change that if you want. Okay, so that's for the ODOM TF. We also we have some parameters. We have pose coariance diagonal that I'm going to put here. Okay. So I can put a space to make it better. And then we have twist coariance diagonal. And I'm not going to go into much more details about that. You see the default values are zero. But if I go here, you see these values should be tuned to your robots sample autotry data. But these values are a good start. And well, basically any configuration I've seen is using those values. So I'm just going to take those and put them here. And I think it's the same. It's the same for both. Yes. Okay. So now when you see this in an other configuration, you know that it's just the default values that you can use from the documentation. Uh the one that they recommend. I'm not an expert in coance. So I'm just going to leave it like this. Okay. If you are more expert than me, then feel free to modify those parameters, but those should work fine. All right, so we go back here and then well, we have open loop. We're not going to use it because we want to close loop control and by default is false. Um, I'm going to use this one still. Enable odom tf. It's true by default. And I'm going to put it here. Enable odom tf. I'm still going to put true. Okay, so just in case later we want to start the controller but not publish the ODOM TF, we can do that. Then uh well this we're going to leave it like this. Okay, so you have the description for each parameter. You might decide to use some of them if you want. I'm also going to put the publish rate. You see that's the publishing rate in Hertz of the autometry and TF messages. And you see this is a double by default is 50 Hz. So, I'm going to put it here. Uh, maybe here. Publish rate. It's okay. Publish rate. And well, let's skip 50 here. It should not be. So, you see the rate here is an integer. The rate here should be a double. Make sure you get that correct. Otherwise, you're going to get some errors. And that's an important thing here is if you have a 50 uh rates here, 50 Hz, but if you only have 10, then uh basically this is going to make all the controllers run at 10 Hz. So if Hz, you cannot have a 50 Hz ODOM TF. Okay

### Segment 11 (50:00 - 55:00) [50:00]

so that's also an important thing to note is if you have too precise some kind of frequencies and publish rates inside controllers, then if this is lower than the global update rate, you might have some well, issues or simply you might be surprised that why it's not working at 50 Hz, why you don't have new data at 50 Hz because this one says that controllers are going to run at 10 Hz. Okay, so I'm going to put 50, and 50. Okay, you can put higher. If I put 100, it means that the controllers are going to run at 100 Hz, including that one. But then the publish rate for the ODOM is still going to be 50. Okay, so it's not going to publish the ODOM at 100 Hz, but only 50. Okay, so that's a nice way to cap this because maybe you will have 1,000 htz. You don't need an ODM at 1,000 htz. Okay, so that's just for the explanation. I'm going to put back uh 50 here. And to finish, well, I'm going to use velocity limits. Uh this also is optional, but I'm just going to show you how to use it. It can be a nice thing to have, okay? Because you might not want your robot to have too high velocity or acceleration, deceleration, etc. Okay, so how to use this? Well, actually I'm using uh well, you see this is an important thing is I was using a different branch. I'm going to use the master branch which corresponds to the latest uh ROS to distribution and well it doesn't change for the rest because the other parameters are going to be the same but one thing you can see already is for this velocity limit here we have linear X max velocity mean velocity etc. If I go to ham which is an older roster to distribution then we have linear X and you see we have has velocity limit so we have a boolean already to enable velocity limits or not and then we can set the max velocity but with the new uh here with the current one I'm using for recording we don't have the has velocity limits so I guess by default it's enabled and we just need to provide a value to set a velocity limit. it. Okay. So, make sure that depending on the ROS to distribution you use, make sure you use also the correct you see on the left the correct branch for your distribution because the parameters might be a bit different. So, let's specify a velocity limit. How do we do this? Well, it's quite simple. You do linear and then dot x dot velocity. Uh actually it's max velocity. Let's go back here. Yes, max velocity. We also have min velocity and it's a double number. So max velocity and let's say 1. 0. And then linear dot x dot min velocity is going to be let's say minus one. And then you can tune those values. You can increase them. This is quite low. Okay, this can be nice to start with a low value just in case because if the controller is working in a weird way, at least you're not going to run the robot at 100 m/s. And we go down here. You see we have X and we also have angular Z. Okay, because for div drive we can basically say move forward or backward and we can say turn right or left. So angular. z Z dot uh max velocity 1. 0 angular Z min mean min velocity minus one. Also pay attention not to make typos because if you make typos in the parameters you might not have an error. It might just be ignored. All right. And I think that should be it. So you see with this controller it was a bit more work to find the different parameters and to set them as we need. Some of them are really important. For example those ones here they're really super important. Then the good thing is once you know how to set the div drive controller for one robot then for another robot it's going to be pretty much the same thing. You just replace the values. And in many examples in ROS2 uh control demos and other examples that you find online, you're going to find similar configurations. Okay? And what people usually do and what I did myself also when I learned uh ROS to control first is well, you just find a configuration and you copy paste for your project and then you tweak some values and you hope that it works. The good thing now I hope with this lesson is that now you understand actually where those values come from and you understand a bit more about how to set them up, how to tune them and how to use the parameters that you actually really need. Okay, so make sure you save the file. All right, and the controller configuration is now complete.

### Segment 12 (55:00 - 60:00) [55:00]

Now that you have a URDF, a ROS to control tag in the URDF to specify the hello interface which now is a mock component. And now that you also have a package with a config for the different controllers you want to use, we can actually start everything. And I'm first going to do that uh directly from the command line. We're going to start each node one by one so you can understand what we need to start. And in next video, we're going to actually create a launch file. Okay. So usually I recommend to do this if you can is to start the stuff directly understand what you need to start and then add it into a launch file. Okay. So the first thing we need is the robot state publisher. This should not be new to you. So ROS to run robot state publisher. This is already the central piece of any ROSS application. Okay. Robot state publisher. So we start the node and then Ross ar with a parameterp the parameter name is robot description and then well here we have this uh syntax to use zacro so dollar sign zacro uh close the parenthesis and then space and we need to specify the zacro file. So that's going to be this one. My robot urf dot uh zero. So what is the path? Well, I'm just going to come use this terminal. We're going to go to our workspace my robot description uh URF. Okay, that's going to be here. I do pwd. I just copy this path. So make sure you copy your path because you don't have the same username as me. and then slash my robot urf. zro. Okay, can just copy to make sure you don't make any typo. Okay, let's just clear this. All right, so ROS to run robot state publisher. Robot state publisher with Ross asks-p. parameter name is robot description and then we use the zacro command with the file and this file contains what contains all the links all the joints and the ros to control tag I press enter you see robot initialized or you see other logs and that's the first thing we have okay we have our robot state publisher node now what we're going to do is we're going to start the controller manager because if you remember from the introduction we're going to start some controllers And those controllers are going to be bound to some hardware interfaces. But how do we do this? We need a controller manager that's from the uh ROSU control packages. So we're going to do ROS to run controller manager. So actually we have a package named controller manager and inside we have a ROS to control node. Okay, you should use the autocomp completion. If it doesn't work, then make sure that you have correctly installed the uh ROS to control node from the introduction. And we are not just going to start it like this. We're going to give it the parameter file here that we have created. And so it's going to have all those parameters and all the controller uh configurations. So we do ROSS ars and then not just one parameter but params dash file and uh we're going to specify. Okay. So here just homem slash I use the absolute path. Okay. It makes things easier. So that's my username and then roster to workspace source my robot bring up config and it should be only one. So my robot controllers. All right. So rest run controller manager name of the package. The name of the node actually name of the executable is roster control node and we pass the parameter file. Let's see if that works. So, what do we have here? So, you see subscribing to robot description topic for the robot description. So, that's why you need to first start the robot state publisher. And then we're going to get the URF as well. Update rate is 50 Hz. Okay, we have some warning here, but it's not a problem. And then you see loading hardware, mobile base hardware interface. And you see here mock components generic system. This is what we have specified in the roster control type. Okay, that's this name here that you see and that this plug-in that you see. Okay, and then we have all the stuff with configure activate that we're going to come back to this later when we create our own hardware interface. Okay, so now what do we have with this? Well, we have the controller manager. If I do ros to node list, you see we have robot state publisher and we have a controller manager node. Okay, you see the name is controller manager. That's why also in the yl file we have controller manager here because

### Segment 13 (60:00 - 65:00) [1:00:00]

that's the name of the node. I know it's a bit confusing. So the controller manager is the name of the package and then we have ros control node for the executable name. But then the node name is controller manager. That's just how it is. All right. So now what's missing is actually we need to kind of activate the uh different uh controllers. We need to start the controllers because we have the name of the controllers here with the configuration. The controller manager knows about them but we need to start them. How to do this. I'm going to do clear here. So we have two terminals already occupied. Robot state publisher and controller manager. Here we're going to do ROS to run controller manager. So same package but then we have a uh executable named spawner. Okay, that's going to spawn that's going to start a controller. I'm going to put that here. So we see the logs and what's going to be uh the name. The name is the name that you have defined here. So I can copy this name here join state broadcaster and put it there. and press enter. And you see, so this node, this spawner node is just going to start spawn something and then exit. Okay. And you can see uh so loaded joint state broadcaster. It's configured and activated. And here on the uh controller manager side, you see that we are loading the controller. Okay. With some logs to say uh all available state interface will be published, etc. All right. Still from the same terminal, I can do ROS to run controller manager spawner. And this time, def drive controller. Make sure it's the same name, okay, as the one you have defined here. And I just press enter. Let's see what we have. Okay, it's working. And you see we have logs here loading controller. You see it's going to use the arguments from the parameter file that we have specified. Okay. And now the robot is actually running with ROS to control. It's a fake hardware. Okay. It's a mock component, but it's working correctly. How can we verify this? How can we actually see something that works? Well, I'm going to uh run avis to run office 22 and I'm going to give a so with dash d configuration and actually in the package that I gave you in the my robot description we have avis config I'm going to use that one okay so I put the absolute path ros to source my robot description rvs and urf config. vis. All right. And you can see the row here. So nothing special. But one first thing you can notice is we don't have an error for the wheels for the TF. Uh it might seem normal, but actually it's a good sign. It means that the joint state broadcaster is working correctly. Okay? Because now we don't have a fake joint state publisher anymore. It's the controller from roster control. And you can see that we have the correct TF for the wheel. They are not moving of course, but they are correctly published in the fixed frame. I can also you see can choose ODM. All right, we have a new TF ODOM to base footprint which now uh you see well it's is the same. You can just check the TF. Uh it's at the same place because the robot hasn't moved. Great. If I do so I have a here and I'm going to control the robot from that terminal here. So if I do ros to node list as you can see I have my controller manager I have my robot state publisher and then I have one node for each controller okay plus one node for arvis if I do ros to topic list I have quite a lot of stuff but you see I have my diff drive controller slash cmdvel okay so you probably are familiar already with the cmdvel kind of uh topic where you send a twist message with a linear and angular velocity. And this is you see this is what's used by the div drive controller. So for the topic name uh I'm not sure but you might be able to change it from the parameters. Uh anyway we're going to use that one. So I do roast to topic info with this. Okay. One thing you can notice is usually for this kind of topic we use a twist but here is a twist stamped. So if I do ros to interface show with twist stamped uh we have still our uh twist with

### Segment 14 (65:00 - 70:00) [1:05:00]

linear x and angular z. That's what we need. But we also have a header with you see a time stamp and that's quite important. that's going to be used uh to decide if the command is recent enough or not to be taken into account. All right. So just know that when you publish on this command velocity topic, you need to specify a twist stamped with the current time. Now there is a node we can use directly from the terminal ros to run teleop twist keyboard and teleop twist keyboard. So this way we can send a common velocity directly by moving arrows on the keyboard. That's going to be much easier to visualize. And actually we cannot just run it like this because it's going to publish a twist message on the / cmd topic. So we need to change first Ross. So Ross args with dash r to rename the cmd2 and actually what was the so topic list? It's that one. Okay. So we make sure that uh instead of publishing on cmd we publish on that. Anyway if you see it doesn't work you start rqt graph and you can easily see that topics are not uh the same. So we change the name of the topic and then uh there is an option for this tup to keyboard that's quite easy. We do an other. So we do dashp for parameter and stamped with colon equal true. This is going to add a header with a time stamp. Okay. So, we don't need to do anything else. All right. I press enter. And then, so I'm gonna have this on one side. I'm going to put a here. And I'm going to zoom out a bit. I choose ODM as the fixed frame. And then you see you have the commands to make the robot move. Let's try. And you see that it is working great. Our robot even if the hardware is a fake hardware but we have correctly configured the controllers and kind of the stack with ROS to controls and the different nodes we need to start so that we can use ROS to control with our robot. All right, you can see it's working. We see the wheels. The wheels are turning. And we even have this TF uh this new TF ODOM 2 base footprint. In this video, we are going to write the launch file so that we can start everything that we have started in the last video. So the robot state publisher, the controller manager, we're going to spawn the different controllers. We're also going to start Alis so we can have this view. Okay. So, I'm going to stop everything. Just make sure you stop everything in case. All right. And close everything. We're going to come back to our package my robot bringup. Here we have a config folder. We're going to add another folder named launch. So, inside my robot bring up at the root of the package you have launch and config. in the cmck list. txt. Very important. You go here and you have config. You're going to put launch. Okay? The order doesn't matter. You make sure you install the config folder and the launch folder. That's all we need to do here. So, I'm going to close this and we don't need to come back to the cake list. txt anymore. Now, in my launch folder, I'm going to add a new file which is going to be well, let's say my robot. dot. And as you know, as I love Python launch files so much, I'm actually going to do the XML one. It's going to be much easier. I'm still going to show you the Python one afterwards, okay? But I'm going to write it in XML. I really recommend XML anyway. I think the Python launch file is overly complicated for pretty much nothing. And just in case you really need to use Python uh for a launch file for some functionalities, you can always include that part inside an XML launch file. Okay, so let's start launch. And we have a launch tag. That's it. And what is the first thing we need to do? Well, we need to start the robot state publisher. And with this, we also need to pass the URDF. Now, the good thing is uh well, I'm not going to reinvent the wheel here. If I go to my robot description in my launch display. xml, that's what we have done. Actually we have already started the robot state publisher with the URDF and you see the syntax is a bit particular. So instead of just reinventing the wheel and making mistake I'm going to take that one. So the variable here URF path. I'm going to copy that and I'm

### Segment 15 (70:00 - 75:00) [1:10:00]

going to put it here. So make sure everything is still correct. Okay. We're going to use the my robot description package. That's this one. And we're going to get this file. And then we're going to start the robot state publisher which is this node here. All right. Robot state publisher. Robot state publisher param name is robot description with the command zacro and the path. Great. Uh then we have the ar stuff. I'm going to keep that for just at the end of the video. We don't need the joint state publisher GUI. This was just for testing. Okay, we're going to use the join state publisher from the ROS to control controllers. So what do we have next? After the robot state publisher, we need to start another node. the controller manager. So if you remember what we did on the command line is from the package controller manager and the executable is ROS2 control node. I'm going to close it like this so that I can add a parameter. So, param and we're going to use from because we're going to include the config file here, the my robot controllers. And well, you could use a variable if you want. I'm just going to put it like this. So, find pkg share. We use find pkg share because everything is installed inside a share folder. I need to put the name of the package. So my robot bringup is this and then slash after the parenthesis is going to be config slash my robot controllers. YAML and I close the parameter. All right. So we start the controller manager node with the parameters here. And so the controller manager is also going to listen to the robot description topic from the robot state publisher. It's going to get all the information with the ROS2 control tag here. It's going to get the information with those parameters. Okay, that's everything we have specified. So now what we can do is we can spawn our different controllers. So we're going to use node because we did the ROS to run. Okay. So it's going to be node here. Controller manager exec is spawner like this. And then we are providing some arguments. So we're going to put args and just the name of the controller. the joint state broadcaster. If you're not sure, you just take the name you have created here. We spawn that one and then node pkg controller manager xec spawner again and we spawn the diff drive controller. Okay, so we spawn the two controllers that we have in our application and that's it. Now we have also started RV because it's nice to visualize what's going on. Okay, to validate that is working. RV is often the best way. So we're going to start RV and actually I don't need to write the code myself because I've already written it in the display launch XML. Okay. So, I'm going to take my RV config path variable and put it there um here in the launch file. Okay. Make sure it's the same config that we are using from my robot description package. And then I can take my AR node right here. So I do ris uh and then the arguments dash d with the configuration. I'm going to save and the launch file is now complete. All right. So we start you see one node here the robot state publisher and then we start the controller manager. Then we spawn the two controllers and we also start our now for the teop keyboard. Well the teop keyboard is something we're going to start on the side. Now what I'm going to do as well is because you see we are using so from this package here we are using the robot state publisher package the controller manager package and we also need the my robot description package plus two. So I'm going to add those in the

### Segment 16 (75:00 - 80:00) [1:15:00]

package. xml XML I'm going to add here after build to depend exec depend robot state publisher exec depend and then exec depend with controller manager and then another exec depend with my robot description Okay, I close the tag and finally exec depend all these two and I close. All right, so that's going to make things a bit cleaner when we build uh the workspace. Let's save that. All right. And if one of those package doesn't exist here or is not installed, then we're going to get an error when we build, not when we run uh the launch file. So let's go ahead. Let's open a terminal. Let's go to our workspace and call build. Okay, I'm going to source and I'm going to do ROS to launch my robot bring up with. So it was my uh launch XML or Python should be the same. Okay, you see this time we have all the logs in the same terminal. All right. As long as you see this blue and this green, it should be okay. You see that we have processed has finished cleanly. This is the spawner. Okay. So when we spawn a node, if you remember, it's just going to spawn the controller and then the node, the spawner node itself is going to finish. So this is not a problem. This is normal and all this is here. All right. And uh I'm going to open a new terminal here and just say um ROS to run. So we have the same thing. We have ROS to topic list. It's going to be the same. We have the div drive uh controller cmdail. Okay. And so if I go back to my commands, I can find this one the roster run tup twist keyboard. I change the name of the cmdvel topic. And I also add a stamped parameter. Okay, let's see if that works. Should be working. It works. So actually you see the robot wheels are moving and I'm uh my fixed frame is the base footprint. If I change to autumn, then you can see the robot moving from its origin point. All right. And I will just do one last thing. I do architect. All right. Um I'm going to hide those. And so what do we have? We have you see centerpiece is the robot state publisher publishing on the TF topic and also on the robot description is publishing the URL. You have the controller manager here and then we have the joint state broadcaster publishing on the join states. So this one is going to receive the data from the hardware which for now is a mock component. So it's a fake hardware and it's going to publish to join state which is going to be received by the robot state publisher and then publish the TF. Now we have the second controller which is the diff drive controller. Okay. And you see that well our application in this case if you remember the introduction I have I had a box on the left which was the application. The application is the tele keyboard. It's going to send the cmdvel command. Okay which is going to go to the controller. The controller is going to control the wheels and also publishing on TF is going to publish the ODOM TF. All right, so you see we have two nodes publishing on TF. Okay, and that's pretty much it for now. All right, that's also the end of this ROS to control crash course on YouTube. I hope you could learn a lot and get a better understanding of how Rosto control works. So you have seen how to adapt a robot with Ross to control with the URDF tags, the configuration for different controllers and the launch file to start everything. Now if you use ROS to control is probably so that you can control real hardware. And here comes the next step for you. You will need to learn how to create a hardware driver and a hardware interface so that you can bridge the ROS2 controllers with your custom hardware. And this is exactly what I teach in my full ROS to control course which contains seven hours of video content, more practice and downloadable code templates for your own projects. If you like the way I teach, you will love this course. Here's actually an overview of what's inside the course. So the course contains seven sections, okay, the introduction section

### Segment 17 (80:00 - 81:00) [1:20:00]

and then the section two and how to adapt a robot to Ross to control with a mock component with mock hardware. So that's basically what we have done here in this crash course more or less. There's one more lesson here, but that's basically what you did. And now the most important part is actually this one. How to create a hardware driver and how to write a hardware interface for ROS to control. So I will show you how to create a pure C++ hardware driver. Okay, give you some tips on how to do that and also how to include this driver inside the ROS node. Then we will write a hardware interface for ROS to control. Okay, we will create a package. We will correctly configure the package, build it and I will explain everything you need to know so that you can create your own interface for your own project. We will then actually then we will do a project. So the section five is a complete new project. Okay. So for now we only have a mobile base but in section five we are going to add a robotic arm on top of the mobile base and control it with our own hardware as well. Okay. So you see I have some motors here and so we're going to do the whole process again to adapt the robot to roster control to add also a hardware interface and to use the hardware driver for those motors and then we have a complete setup also an extra step on how to use roster control with the gazebo simulator. And that's not all. There is also another section 1 hour on how to create a custom controller. So then after this you can create your own custom hardware interface, your own custom controller. Okay, you know how to start everything and you will have full control over roster control. All right, thank you for watching and I hope to see you in the course.
