Launch Files and Packages
Introduction
ROS 2 packages organize related nodes, launch files, and resources. Launch files automate starting multiple nodes with specific configurations.
Learning Objectives:
- Create ROS 2 packages with proper structure
- Write launch files to start multiple nodes
- Build packages with colcon
- Manage dependencies
What is a ROS 2 Package?
A package is the basic unit of ROS 2 software organization containing:
- Nodes: Executable programs
- Launch files: Automation scripts
- Configuration: Parameters, URDF files
- Dependencies: Other packages required
Package Structure
my_robot_pkg/
├── package.xml # Package metadata and dependencies
├── setup.py # Python package setup
├── setup.cfg # Install configuration
├── my_robot_pkg/ # Python source code
│ ├── __init__.py
│ └── my_node.py
├── launch/ # Launch files
│ └── robot.launch.py
├── config/ # Configuration files
│ └── params.yaml
└── urdf/ # Robot descriptions
└── robot.urdf
Creating a Package
# Navigate to workspace src directory
cd ~/ros2_ws/src
# Create Python package
ros2 pkg create --build-type ament_python my_robot_pkg \
--dependencies rclpy std_msgs
# Create C++ package
ros2 pkg create --build-type ament_cmake my_cpp_pkg \
--dependencies rclcpp std_msgs
Package.xml
<?xml version="1.0"?>
<package format="3">
<name>my_robot_pkg</name>
<version>1.0.0</version>
<description>My robot package</description>
<maintainer email="you@example.com">Your Name</maintainer>
<license>Apache-2.0</license>
<!-- Build dependencies -->
<depend>rclpy</depend>
<depend>std_msgs</depend>
<depend>sensor_msgs</depend>
<test_depend>ament_copyright</test_depend>
<test_depend>ament_flake8</test_depend>
<test_depend>ament_pep257</test_depend>
<export>
<build_type>ament_python</build_type>
</export>
</package>
Building Packages with Colcon
# Navigate to workspace root
cd ~/ros2_ws
# Build all packages
colcon build
# Build specific package
colcon build --packages-select my_robot_pkg
# Build with symlink (no rebuild for Python changes)
colcon build --symlink-install
# Source the workspace
source install/setup.bash
Launch Files
Launch files start multiple nodes with configurations in one command.
Python Launch File (Recommended)
# launch/robot.launch.py
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(
package='my_robot_pkg',
executable='camera_node',
name='camera',
output='screen',
parameters=[{'frame_rate': 30}]
),
Node(
package='my_robot_pkg',
executable='controller_node',
name='controller',
output='screen',
remappings=[
('/input', '/camera/image'),
]
),
])
Running Launch Files
# Run launch file
ros2 launch my_robot_pkg robot.launch.py
# Pass arguments
ros2 launch my_robot_pkg robot.launch.py use_sim:=true
Launch File with Parameters
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node
import os
from ament_index_python.packages import get_package_share_directory
def generate_launch_description():
# Declare arguments
use_sim_arg = DeclareLaunchArgument(
'use_sim',
default_value='false',
description='Use simulation time'
)
# Load parameter file
config = os.path.join(
get_package_share_directory('my_robot_pkg'),
'config',
'params.yaml'
)
# Define nodes
robot_node = Node(
package='my_robot_pkg',
executable='robot_node',
name='robot',
parameters=[config, {'use_sim_time': LaunchConfiguration('use_sim')}],
output='screen'
)
return LaunchDescription([
use_sim_arg,
robot_node,
])
Parameter File (YAML)
# config/params.yaml
robot_node:
ros__parameters:
max_speed: 1.0
min_distance: 0.5
update_rate: 10.0
robot_name: "my_robot"
Including Other Launch Files
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from ament_index_python.packages import get_package_share_directory
import os
def generate_launch_description():
# Include Gazebo launch
gazebo_launch = IncludeLaunchDescription(
PythonLaunchDescriptionSource([
os.path.join(get_package_share_directory('gazebo_ros'), 'launch'),
'/gazebo.launch.py'
])
)
return LaunchDescription([
gazebo_launch,
# Your nodes here
])
Workspace Workflow
# 1. Create workspace
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws/src
# 2. Create package
ros2 pkg create my_robot_pkg --build-type ament_python
# 3. Write code in my_robot_pkg/my_robot_pkg/
# 4. Update setup.py entry points
# entry_points={
# 'console_scripts': [
# 'my_node = my_robot_pkg.my_node:main',
# ],
# },
# 5. Build
cd ~/ros2_ws
colcon build --symlink-install
# 6. Source
source install/setup.bash
# 7. Run
ros2 run my_robot_pkg my_node
Best Practices
- One package per robot/subsystem: Don't mix unrelated code
- Use launch files: Don't start nodes manually
- Parameter files for config: Keep parameters in YAML files
- Symlink install for Python: Faster iteration with
--symlink-install - Declare dependencies: Add all dependencies to
package.xml
Exercises
- Create a ROS 2 package for a simple robot
- Write a launch file that starts a publisher and subscriber
- Add a parameter file and load it in the launch file
- Build and run your package
Summary
ROS 2 packages organize code, dependencies, and resources. Launch files automate multi-node startup. Colcon builds packages in a workspace.