How To Set up a ROS2 Project for Python – Foxy Fitzroy


In this tutorial, we will learn how to set up a ROS2 project from scratch.


Source Your ROS2 Installation

We first need to create a new workspace. A workspace is a folder that will contain all your ROS packages.

Here is the official tutorial, but I’ll walk through all the steps below.

Open a new terminal window.

To find out which version of ROS2 you have installed, type the following command:

printenv ROS_DISTRO

I’m using the foxy distribution of ROS2.

Now, let’s source the ROS2 environment. Type the following command:

source /opt/ros/foxy/setup.bash

Create a Workspace

Let’s create a workspace directory. “-p” is short for “–parents”. This flag makes sure the mkdir (“make directory”) command makes the parent /dev_ws/ folder as well as the /src/ folder within it (Feel free to check out my Linux commands tutorial).

mkdir -p ~/dev_ws/src
cd ~/dev_ws/src

The syntax is:

mkdir -p ~/<yourworkspace>_ws/src

cd ~/<yourworkspace>_ws/src

Create a Package

Now let’s create a ROS package.

We will use the following syntax.

ros2 pkg create –build-type ament_python <package_name>

Type this command:

ros2 pkg create --build-type ament_python my_package

Your package named my_package has now been created.

Build Your Package

Return to the root of your workspace:

cd ~/dev_ws

Build all packages in the workspace.

colcon build

If you only want to build my_package, you can type

colcon build --packages-select my_package

Source the Setup File

Open a new terminal window.

Source your ROS2 installation.

source /opt/ros/foxy/setup.bash

Move to your workspace folder.

cd ~/dev_ws

Add the files you just created to the path.

source install/setup.bash

If you don’t have gedit installed, install it using this command:

sudo apt-get install gedit

Open your .bashrc file.

gedit ~/.bashrc

Add this line of code to the very bottom of the file.

source /opt/ros/foxy/setup.bash

You now don’t have to source your ROS2 installation every time you open a new terminal window.

While you’re at it add this line of code to the very bottom of the .bashrc file.

source ~/dev_ws/install/setup.bash

The syntax is

source ~/<your_workspace>/install/setup.bash

Save the file, and close it.

Your system now knows where to find your ROS2 packages.

Write Node(s)

Move to the dev_ws/src/my_package/my_package folder.

cd dev_ws/src/my_package/my_package

Write a Python program (i.e. node), and add it to this folder you’re currently in. This post has some sample code you can use. Copy the Publisher Node code, and paste it into a file named


Save the file and close it.

Now change the permissions on the file.

chmod +x

Make sure that the names of your python nodes are not the same as the name of the package. Otherwise, you will have ImportErrors.

You can add as many Python programs as you like. For example, you might have one node that defines a class, and then you have another node that imports that class and uses it to make calculations, which are then published to a ROS2 topic as some data type (e.g. Float64, geometry_msgs/Twist, etc.).

Add Dependencies

Navigate one level back.

cd ..

You are now in the dev_ws/src/my_package/ directory. 



You should see the, setup.cfg, and package.xml files.

Open package.xml with your text editor.

gedit package.xml

Fill in the <description>, <maintainer>, and <license> tags.

Add a new line after the ament_python build_type dependency and add the following dependencies which will correspond to other packages the packages in this workspace needs (this will be in your node’s import statements):


This let’s the system know that this package needs the rclpy and geometry_msgs packages when its code is executed. 

The code doesn’t need the geometry_msgs package, but I’m having you add it anyway just to show you that you can add all sorts of message types in this package.xml file.

Save the file.

Add an Entry Point

Now we need to add the entry points for the node(s) by opening the file.


Make sure this code is in there:

        'console_scripts': [
                'my_python_script = my_package.my_python_script:main',

The syntax is:

‘my_python_script = my_package.my_python_script:main’

my_python_script will be the name of the executable.

‘my_package.my_python_script:main’ tells the system to execute the main() function inside Therefore, this will be the entry point when you run your node.

The executable script will go to:


Save and close it.

Check for Missing Dependencies

Check for any missing dependencies before you build the package.

Move to your workspace folder.

cd ~/dev_ws

Run the following command:

rosdep install -i --from-path src --rosdistro <distro> -y

For example:

rosdep install -i --from-path src --rosdistro foxy -y

I get a message that says:

“#All required rosdeps installed successfully”

Build and Run

Now, build your package by first moving to the src folder.

cd src

Then build the package.

colcon build --packages-select my_package

You should get a message that says:

“Summary: 1 package finished [<time it took in seconds>]”

Open a new terminal tab.

cd ~/dev_ws

Run the node:

ros2 run my_package my_python_script

The syntax is:

ros2 run <package_name> <node name without the .py>

Open a new terminal tab, and move to the root directory of the workspace.

cd ~/dev_ws

List the active topics.

ros2 topic list -t

To listen to any topic, type:

ros2 topic echo /topic_name

Where you replace “/topic_name” with the name of the topic. 

When you’ve had enough, type Ctrl+C in each terminal tab to stop the nodes from spinning.

Zip the Workspace for Distribution

If you ever want to zip the whole workspace and send it to someone, open a new terminal window.

Move to the directory containing your workspace.

cd ~/dev_ws
cd ..
zip -r /dev_ws

The syntax is:

zip -r <> <foldername>