5. Workspaces and your first package

So far we have only used what came pre-installed. Now we build our own.

What a workspace is

A folder holding your code and the results of building it:

~/ros2_ws/
├── src/          ← your code (the only part you maintain)
├── build/        ← intermediate build files (safe to delete)
├── install/      ← what actually runs (safe to delete)
└── log/          ← build logs (safe to delete)

The bottom three can always be regenerated by building again — do not commit them to git.

Create a workspace

mkdir -p ~/ros2_ws/src
cd ~/ros2_ws
colcon build

The first colcon build has nothing to build, but it creates the folder layout.

Create your first package

A package is a unit of code; one workspace holds many.

cd ~/ros2_ws/src
ros2 pkg create --build-type ament_python my_robot --dependencies rclpy

You get:

my_robot/
├── package.xml         ← name, version, dependencies
├── setup.py            ← what gets installed, and the command names
├── setup.cfg
├── resource/my_robot
└── my_robot/           ← your .py files go here
    └── __init__.py

Note

--build-type ament_python is Python; use ament_cmake for C++.

Start with Python — changes take effect immediately with no compile step. Move to C++ later, for the parts that genuinely need the speed.

Build

cd ~/ros2_ws
colcon build --symlink-install

Tip

Always use --symlink-install while developing.

By default colcon build copies your Python files into install/, so every edit needs a rebuild or you run the old code.

--symlink-install creates links back to src/ instead — edit and run, no rebuild (unless you add a new file or change setup.py).

Skipping this costs a lot of time in “I changed the code and nothing happened”.

Build a single package once the workspace grows:

colcon build --symlink-install --packages-select my_robot

source — the most forgotten step

After every build you must source before your code is callable:

source ~/ros2_ws/install/setup.bash

Danger

🔴 This is the number one cause of “the code is right, why does it not work”.

Symptoms:

  • Package 'my_robot' not found even though the build succeeded

  • You edit the code and the behaviour does not change

  • It works in one terminal and not in another

Every new terminal needs both /opt/ros/humble/setup.bash and ~/ros2_ws/install/setup.bash.

The order matters — ROS first, workspace second:

source /opt/ros/humble/setup.bash        # ① ROS first
source ~/ros2_ws/install/setup.bash      # ② workspace second

You can put both in ~/.bashrc, with the caveat from topic 2.

rosdep — install what a package needs

When using someone else’s code, or moving to a new machine:

cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y

It reads every package.xml and installs the missing dependencies.

When the build fails

colcon build --symlink-install 2>&1 | tail -40

For strange errors you cannot explain, delete the build output and start clean:

cd ~/ros2_ws
rm -rf build install log
colcon build --symlink-install

Warning

Only build, install, and log — never delete src, that is your code.


Previous: 4. Command-line tools · Next: 6. Writing a publisher and subscriber