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 foundeven though the build succeededYou 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