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 buildcompiles/stages every package undersrc/intobuild/andinstall/.- 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 type | Language | Manifest hints |
|---|---|---|
ament_python | Python | setup.py, setup.cfg, package.xml |
ament_cmake | C++ | 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-runcolcon buildand check its output, then sourceinstall/setup.bashagain.- 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—colconitself is not installed (it's a separate tool from the ROS 2 distro on some minimal installs). Installpython3-colcon-common-extensionsfor your distro/OS.rosdepcomplains about an unknown key — the dependency name inpackage.xmldoes not match a known rosdep key. Confirm the spelling and thatrosdep updatehas 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 buildproducesbuild/,install/, andlog/. ros2 pkg create --build-type ament_pythonscaffolds a working Python package with the right manifest and entry-point wiring.rosdep install --from-paths src --ignore-src -r -yresolves dependencies declared in every package'spackage.xml.- Use
--symlink-installwhile iterating on Python nodes to avoid rebuilding for every code change. - Always source
install/setup.bashafter 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.