# 5. ROS Packages and Workspace

Software in ROS is organized in [packages](http://wiki.ros.org/Packages#:~:text=A%20ROS%20package%20is%20simply,and%20the%20unit%20of%20release.). **A package is a directory containing executables and supporting files that serve a specific purpose**. For example, you can have a package for handling reading and processing images from a camera. After building (compiling) your package (more on this later), you can call or investigate your program in a terminal. **ROS packages are placed in another directory called a *catkin* workspace** because they are built with *catkin* tools.

![catkin_workspace.jpg](https://cdn.hashnode.com/res/hashnode/image/upload/v1669564141260/GaJNou4S2.png align="center")

In the example above, there are 3 packages named: *hand\_gesture\_recognition*, *my\_cam*, and *ros\_mobile\_robot* which are placed in the folder *src* inside the workspace folder named *catkin\_ws*. The other folders: *build, devel,* and *logs* are automatically generated after the packages are built. So, either ROS packages or workspace, just think about them as folders with specific required components that I will mention below.

# Create a catkin workspace

According to the [official ROS website](http://wiki.ros.org/catkin/conceptual_overview), "The name catkin comes from the tail-shaped flower cluster found on willow trees -- a reference to Willow Garage where catkin was created." For now, you should only need to keep in mind that *catkin* is the official build system of ROS. If you want to know more about it, give [this](http://wiki.ros.org/catkin/conceptual_overview) a read.

A workspace is nothing but a folder, so you create one simply by making a new folder. You can either right-click in the Home folder (where we can easily access it) and choose **New Folder**, or use the shortcut **Ctrl + Shift + N**. Then, you also need to create a folder **src** inside your workspace folder. Since we are using Linux, let's do it the "Linux" way by executing commands in a terminal. Open a terminal and type:

```bash
mkdir -p ~/catkin_ws/src
```

`mkdir` means **m**a**k**ing **dir**ectory, `-p` means parents, and `~` is short for the Home folder. This command will create a folder named **catkin\_ws** (again, you can name it anything you like) with a subfolder named **src**. Pretty convenient, right? Then, change the working directory of the current terminal to the workspace folder by using the `cd` command (`cd` means **c**hange **d**irectory):

```bash
cd ~/catkin_ws
```

Now even though there are no packages in your workspace, you can start building it by using the `catkin_make` or `catkin build` command. I prefer `catkin build` mainly because with `catkin_make`, it always builds all the packages which will take a long time if the workspace contains many packages. With `catkin build`, it is possible to build each package separately. Remember to run `source ~/catkin_ws/build/setup.bash` beforehand if you have not done it when opening the terminal or have not put this command in the `.bashrc` yet.

```bash
catkin build
```

After building successfully, your terminal should look like the photo below, and the three folders *build, devel, logs* are also generated.

![build_catkin_ws.jpg](https://cdn.hashnode.com/res/hashnode/image/upload/v1669582961614/js7dhqwIs.png align="center")

# Create a ROS package

As mentioned above, a ROS package is also a folder placed in the **src** folder of a workspace. However, there are several must-have components that make up a package. They are (this is basically copied from [here](http://wiki.ros.org/catkin/Tutorials/CreatingPackage)):

* A **package.xml** file provides meta-information about the package.
    
* A **CMakeLists.txt** which uses catkin.
    
* Also, each package must have its own folder meaning no nested packages nor multiple packages sharing the same directory.
    

So what should be included in *package.xml* and *CMakeLists.txt*? What are they exactly and why do we need them? Let's find out the answer by just try creating a package. Fortunately, there is a command called `catkin_create_pkg` for doing that. Assume that we want to create a package named *my\_cam* to read images from our webcam and publish them (the definition of `publish` will come in the [next chapter](https://robodev.blog/ros-basic-concepts). Open a terminal and direct it to the `~/catkin_ws/src`:

```bash
cd ~/catkin_ws/src
```

then run

```bash
catkin_create_pkg my_cam rospy sensor_msgs
```

This will create a package (i.e. folder) **my\_cam** with two dependencies *rospy* and *sensor\_msgs* (I will explain what they are in the next chapter). Inside *my\_cam* there are 2 files **package.xml** and **CMakeLists.txt** and a folder **src** like below.

![catkin_create_pkg_example.jpg](https://cdn.hashnode.com/res/hashnode/image/upload/v1669703699384/xNzuMzmuQ.png align="center")

## Inside *package.xml* and *CMakeLists.txt*

Open the *package.xml* and you will find all the information about the package such as the name of maintainers, type of license, and dependencies. Most of the file is commented out (e.g. this is a comment: `<!-- The *depend tags are used to specify dependencies -->`). In the photo below, I already deleted all the comments

![ros_package_xml.jpg](https://cdn.hashnode.com/res/hashnode/image/upload/v1669788948395/6kwdcEPXv.png align="center")

For those of you who have never worked with [XML](https://en.wikipedia.org/wiki/XML) before, it is a markup language similar to [HTML](https://en.wikipedia.org/wiki/HTML) which describes elements by *tags*. For instance, the line `<name>my_cam</name>` means the *package name* is defined as `my_cam` using the opening tag `<name>` and closing tag `</name>`.

Next, open the *CMakeLists.txt*. It also has lots of comments (beginning with `#`) mainly for instruction. If you work with C/C++ before, you already know that a [CMakeLists](https://www.jetbrains.com/help/clion/cmakelists-txt-file.html) is used for programs like CMake to find and link all libraries needed to build your package. At the line `find_package`, you can see the two dependencies `rospy` and `sensor_msgs`, which we declared from the command above, are listed. If you had forgotten to declare them, just open the `CMakeLists` and manually edit.

```bash
find_package(catkin REQUIRED COMPONENTS
  rospy
  sensor_msgs
)
```

## Difference between *package.xml* and *CMakeLists.txt*

You may notice both *package.xml* and *CMakeLists.txt* seem to overlap because many pieces of information are similar (project name, dependencies, etc.). There is a very [good answer](https://answers.ros.org/question/217475/cmakeliststxt-vs-packagexml/) to what are the differences and why we need both. In short, here are important points:

* *package.xml* contains meta-data (author, maintainer, URL, description and license) that is not necessary to build (or run) a package, but is still needed for ROS to find information about the package (because the information in CMakeLists is not easily parsed without CMake. It is also needed for displaying package information on the ROS wiki for example.
    
* *CMakeLists.txt* is a build script used by programs like CMake to find and link all the libraries needed to build packages.
    

Don't be discouraged if all of these overwhelm you. You will get used to them soon. For now, just remember that a ROS package always requires the 2 files *package.xml* and *CMakeLists.txt*, and a folder *src* is where you keep your code.

Wow, that's a long post and we made it! In the [coming parts](https://robodev.blog/ros-basic-concepts), we will go through all the core concepts of ROS: Topic, Node, Publisher, Subscriber, etc., and start writing some codes for our *my\_cam* package. Meet you there!

# Summary

* A ROS package is a folder containing executables and supporting files that serve a specific purpose.
    
* A ROS workspace is a folder where you modify, build, and install packages using *catkin* tools.
    
* Two files *package.xml* and *CMakeLists.txt* must be included in a package. To create a package, use the command `catkin_create_pkg`.
    

# Reference

1. Cover photo: [http://wiki.ros.org/groovy](http://wiki.ros.org/groovy)
