Skip to main content

Workspace and Package

Custom ROS 2 packages are typically developed inside a colcon workspace. This page sets up the workspace and package used by the hands-on examples in Publisher/Subscriber, Services and Actions, and Parameters and Launch.

Overview​

A workspace is a directory with a specific layout (src/, and after building, build/, install/, log/) that colcon — the standard ROS 2 build tool — understands. A package is a directory inside src/ with a manifest (package.xml) describing its name, dependencies, and build type.

ros2_ws/
├── src/
│ └── my_package/
│ ├── package.xml
│ ├── setup.py # (Python package)
│ └── my_package/
│ └── my_node.py
├── build/ # generated by colcon build
├── install/ # generated by colcon build — this is what you source
└── log/ # generated by colcon build

Why It Matters​

Nearly every ROS 2 error message that mentions "package not found" or "no executable found" traces back to a few common causes: the workspace was not built successfully, the workspace overlay was not sourced, or the executable was not correctly installed or registered in the package.

Core Concepts​

Workspace vs. Package vs. Install​

  • A workspace can contain many packages.
  • colcon build compiles/stages every package under src/ into build/ and install/.
  • Sourcing install/setup.bash (an overlay) makes those packages usable, on top of the ROS 2 distro (the underlay) you sourced earlier — see CLI Basics.

Build Types​

ROS 2 packages are typically one of:

Build typeLanguageManifest hints
ament_pythonPythonsetup.py, setup.cfg, package.xml
ament_cmakeC++CMakeLists.txt, package.xml

This documentation pack uses ament_python, matching the Python examples in the rest of this section.

Dependency Management with rosdep​

Packages declare their dependencies in package.xml (for example <depend>rclpy</depend>). rosdep reads these declarations across every package in src/ and installs the corresponding system/ROS packages:

# One-time setup (skip if already initialized on this machine/container)
sudo rosdep init
rosdep update

# Run from the workspace root, before building
rosdep install --from-paths src --ignore-src -r -y

-r tells rosdep to continue processing other dependencies when an installation error occurs instead of stopping immediately; -y skips interactive confirmation.

Hands-on Steps​

1. Create the Workspace​

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

2. Create a Python Package​

cd ~/ros2_ws/src
ros2 pkg create --build-type ament_python --license Apache-2.0 my_ros2_tutorial \
--dependencies rclpy std_msgs

This generates:

my_ros2_tutorial/
├── package.xml
├── setup.py
├── setup.cfg
├── resource/
│ └── my_ros2_tutorial
├── test/
└── my_ros2_tutorial/
└── __init__.py

The Python examples in Publisher/Subscriber add node files under my_ros2_tutorial/my_ros2_tutorial/.

3. Resolve Dependencies​

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

4. Build with colcon​

cd ~/ros2_ws
colcon build --symlink-install

--symlink-install symlinks Python package files into install/ instead of copying them, so ordinary edits to .py source files usually take effect without rebuilding. Changes to package metadata, dependencies, or console_scripts entry points still require a rebuild.

To build only one package (faster once the workspace has many):

colcon build --packages-select my_ros2_tutorial

5. Source the Overlay​

source ~/ros2_ws/install/setup.bash

Do this in every new terminal that needs to run the package. Confirm it worked:

ros2 pkg list | grep my_ros2_tutorial

Expected Result​

colcon build finishes without errors, printing a summary such as Summary: 1 package finished. After sourcing install/setup.bash, ros2 pkg list | grep my_ros2_tutorial prints the package name.

Useful Commands​

# Build
colcon build # build every package in src/
colcon build --symlink-install # symlink Python files (recommended while developing)
colcon build --packages-select <name> # build one package only
colcon build --packages-up-to <name> # build a package and its workspace dependencies

# Clean rebuild
rm -rf build/ install/ log/
colcon build

# Dependency management
rosdep install --from-paths src --ignore-src -r -y

# Inspecting packages
ros2 pkg list
ros2 pkg xml <package_name> # print package.xml contents
ros2 pkg prefix <package_name> # where it installed to

Common Problems​

  • Package 'my_ros2_tutorial' not found — the overlay was never sourced in this terminal, or the build failed silently earlier. Re-run colcon build and check its output, then source install/setup.bash again.
  • Edits to a Python node have no effect — the workspace may have been built without --symlink-install. Rebuild the package, or clean the generated directories and rebuild with --symlink-install.
  • colcon: command not found — colcon itself is not installed (it's a separate tool from the ROS 2 distro on some minimal installs). Install python3-colcon-common-extensions for your distro/OS.
  • rosdep complains about an unknown key — the dependency name in package.xml does not match a known rosdep key. Confirm the spelling and that rosdep update has been run recently.
  • Mixed underlay/overlay confusion — always source the ROS 2 distro underlay first, then the workspace overlay, in that order, in every new terminal. See CLI Basics.

Key Takeaways​

  • A workspace holds many packages under src/; colcon build produces build/, install/, and log/.
  • ros2 pkg create --build-type ament_python scaffolds a working Python package with the right manifest and entry-point wiring.
  • rosdep install --from-paths src --ignore-src -r -y resolves dependencies declared in every package's package.xml.
  • Use --symlink-install while iterating on Python nodes to avoid rebuilding for every code change.
  • Always source install/setup.bash after building, in every terminal that needs the package.

Next​

Continue to Publisher/Subscriber to add your first working nodes to the my_ros2_tutorial package created here.