Skip to content

2.1 ROS2 Installation and Core Concepts

What You'll Learn

Get ROS2 running and understand the fundamental concepts:

  • What ROS2 is and why it matters for drones
  • Install ROS2 Humble on Ubuntu 22.04
  • Understand nodes, topics, messages, services, and interfaces
  • Learn how ROS2 workspaces function
  • Master essential command-line tools
  • Set up your workspace for drone development

Time: 60-75 minutes


Prerequisites

Before starting, you must have completed:

  • Phase 1 complete (SITL + Gazebo working)
  • Ubuntu 22.04 LTS
  • ~/simtofly_ws/ros2_ws directory exists

What is ROS2?

ROS is Not an Operating System

Despite its name, ROS (Robot Operating System) is not an operating system like Ubuntu or Windows. It's a robotics middleware framework — a collection of tools, libraries, and conventions that help you build robot software.

Aspect Operating System (Ubuntu) ROS2
What it does Manages hardware, files, processes Helps robot components communicate
Runs on Bare metal / VM On top of an OS (Ubuntu)
Examples Ubuntu, Windows, macOS ROS2 Humble, ROS2 Jazzy
Purpose General computing Robotics development

Think of it this way:

  • Ubuntu = The foundation of your house
  • ROS2 = The electrical wiring that connects all rooms

Why ROS2 for Drones?

In Phase 1, you controlled drones through MAVProxy commands:

mode GUIDED
arm throttle
takeoff 10

This works, but has limitations:

  • Manual typing — Can't automate complex decisions
  • No sensor integration — Hard to add cameras, lidars
  • Limited logic — Can't easily do "if battery < 20%, go home"
  • No standardization — Your code won't work with other robots

ROS2 solves these problems:

  • Programmable — Write Python/C++ code for complex behaviors
  • Modular — Each component is independent, easy to swap
  • Standardized — Same patterns work for drones, arms, cars
  • Ecosystem — Thousands of ready-made packages
  • Industry standard — Used by NASA, Amazon, Boston Dynamics

Why ROS2, Not ROS1?

ROS1 (original ROS) was created in 2007. ROS2 is a complete rewrite with:

Feature ROS1 ROS2
Real-time support Limited Built-in
Security None Encryption, authentication
Multi-robot Difficult Native support
Platforms Linux only Linux, Windows, macOS
Status End of life (2025) Active development

Always use ROS2 for new projects. ROS1 tutorials you find online won't work with our setup.


Install ROS2 Humble

ROS2 Humble is the LTS (Long Term Support) release for Ubuntu 22.04, supported until 2027.

Set Locale

ROS2 requires UTF-8 locale. Check yours:

locale # check for UTF-8

Look for UTF-8 in the output. If you see it, skip ahead. If not:

sudo apt update && sudo apt install locales
sudo locale-gen en_US en_US.UTF-8
sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
export LANG=en_US.UTF-8

locale  # verify settings
Expected output:

Verify locale


Add ROS2 Repository

Ubuntu doesn't include ROS2 by default. We need to add the official repository.

Enable Universe repository:

sudo apt install software-properties-common
sudo add-apt-repository universe

Add the ROS2 GPG key (verifies packages are authentic):

sudo apt update && sudo apt install curl -y

export ROS_APT_SOURCE_VERSION=$(curl -s https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest | grep -F "tag_name" | awk -F\" '{print $4}')

curl -L -o /tmp/ros2-apt-source.deb "https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.$(. /etc/os-release && echo ${UBUNTU_CODENAME:-${VERSION_CODENAME}})_all.deb"

sudo dpkg -i /tmp/ros2-apt-source.deb

Install ROS2 Humble

Update package list:

sudo apt update
Upgrade package list:

ROS 2 packages are built on frequently updated Ubuntu systems. It is always recommended that you ensure your system is up to date before installing new packages.

sudo apt upgrade
Install ROS2 desktop (includes visualization tools):

sudo apt install ros-humble-desktop -y

This takes: 10-15 minutes depending on internet speed.

What's included:

  • Core ROS2 libraries
  • RViz2 (visualization)
  • Demo nodes for testing
  • Common message types

Install Development Tools

For building ROS2 packages:

sudo apt install ros-dev-tools python3-colcon-common-extensions -y

Source ROS2 Setup

ROS2 isn't available in your terminal until you "source" it:

source /opt/ros/humble/setup.bash

What does sourcing do?

  • Adds ROS2 commands to your PATH
  • Sets environment variables ROS2 needs
  • Makes ROS2 tools available

Problem: You'd need to run this every time you open a terminal.

Solution: Add it to your bashrc (runs automatically):

echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
source ~/.bashrc

Check the ROS_DISTRO Environment Variable

echo $ROS_DISTRO

Expected output:

ROS_DISTRO Environment

humble

Test some examples

Test with demo nodes. Open two terminals:

Terminal 1 — Publisher (talker):

ros2 run demo_nodes_cpp talker

Terminal 2 — Subscriber (listener):

ros2 run demo_nodes_cpp listener

Expected:

  • Terminal 1 prints: Publishing: 'Hello World: 1', 'Hello World: 2'...

  • Terminal 2 prints: I heard: [Hello World: 1], [Hello World: 2]...

Press Ctrl+C in both terminals to stop.

You should see the talker saying that it’s Publishing messages and the listener saying I heard those messages. This verifies both the C++ and Python APIs are working properly. If this works, ROS2 is installed correctly.


ROS2 Core Concepts

This section explains the fundamental building blocks of ROS2. Understanding these is essential before working with MAVROS and drone control.


Concept 1: Nodes

A node is a single executable program that does one specific job.

Real-world analogy:

Think of a drone as a company. Each employee (node) has one job:

  • Receptionist — answers calls (receives commands)
  • Accountant — tracks money (monitors battery)
  • Pilot — flies the plane (controls motors)
  • Navigator — plans routes (calculates waypoints)

Each works independently, but they communicate to achieve the company's goals.

In ROS2:

Node Job
mavros_node Translates ROS2 ↔ MAVLink
telemetry_node Monitors drone state
mission_node Executes waypoint missions
camera_node Processes camera images

Why separate nodes?

  • Isolation — If camera node crashes, drone keeps flying
  • Reusability — Same telemetry node works for any drone
  • Modularity — Swap components without rewriting everything
  • Distributed — Nodes can run on different computers

Node commands:

# List all running nodes
ros2 node list

# Get details about a node
ros2 node info /node_name

Example output of ros2 node info:

/mavros_node
  Subscribers:
    /mavros/setpoint_position/local: geometry_msgs/msg/PoseStamped
  Publishers:
    /mavros/state: mavros_msgs/msg/State
    /mavros/local_position/pose: geometry_msgs/msg/PoseStamped
  Service Servers:
    /mavros/cmd/arming: mavros_msgs/srv/CommandBool

This shows what data the node sends, receives, and what services it provides.


Concept 2: Topics

A topic is a named channel for streaming data. Nodes publish data to topics, other nodes subscribe to receive it.

Real-world analogy: Think of topics like radio stations:

  • Radio station "FM 101.5 Traffic" broadcasts traffic updates
  • Anyone with a radio can tune in
  • The station doesn't know (or care) who's listening
  • Multiple people can listen simultaneously

In ROS2:

Publisher Node                Topic                    Subscriber Nodes
     │                          │                            │
     │    ┌─────────────────────┴──────────────────────┐     │
     │    │                                            │     │
   MAVROS ──publishes──► /mavros/local_position/pose   ──►  Your Node
                                                       ──►  RViz
                                                       ──►  Logger

Key characteristics:

  • One-to-many — One publisher, unlimited subscribers
  • Anonymous — Publisher doesn't know who subscribes
  • Asynchronous — Publisher sends whenever ready, subscribers receive when available
  • Continuous — Data keeps flowing (unlike services)

Drone topics you'll use:

Topic Direction Data
/mavros/state Drone → You Armed, mode, connected
/mavros/local_position/pose Drone → You Position (x, y, z)
/mavros/battery Drone → You Voltage, percentage
/mavros/setpoint_position/local You → Drone Where to fly

Topic commands:

# List all topics
ros2 topic list

# See data flowing on a topic
ros2 topic echo /topic_name

# Check how fast data is published
ros2 topic hz /topic_name

# Get topic information
ros2 topic info /topic_name

Example — watching drone state:

ros2 topic echo /mavros/state

Output:

header:
  stamp:
    sec: 1234567890
    nanosec: 123456789
  frame_id: ''
connected: true
armed: false
guided: false
mode: STABILIZE
---

The --- separates each message. Data keeps flowing until you press Ctrl+C.


Concept 3: Messages

A message defines the structure of data sent on a topic. It's like a form with specific fields.

Real-world analogy:

When you order food delivery, the order form has specific fields:

  • Name
  • Address
  • Items
  • Payment method

You can't just write free text — the system expects structured data.

In ROS2:

The topic /mavros/local_position/pose uses message type geometry_msgs/msg/PoseStamped:

geometry_msgs/msg/PoseStamped
├── header
│   ├── stamp (time)
│   └── frame_id (string)
└── pose
    ├── position
    │   ├── x (float)
    │   ├── y (float)
    │   └── z (float)
    └── orientation
        ├── x (float)
        ├── y (float)
        ├── z (float)
        └── w (float)

Common message packages:

Package Contains Examples
std_msgs Basic types String, Int32, Float64, Bool
geometry_msgs Geometry Point, Pose, Twist, Vector3
sensor_msgs Sensors Image, LaserScan, NavSatFix
mavros_msgs MAVROS specific State, Waypoint, CommandBool

Message commands:

# See message structure
ros2 interface show geometry_msgs/msg/PoseStamped

# List all available message types
ros2 interface list | grep msg

Why does this matter?

When you write code to read drone position, you need to know the structure:

# You need to know that position is inside pose
x = msg.pose.position.x
y = msg.pose.position.y
z = msg.pose.position.z

Without understanding the message structure, you can't access the data.


Concept 4: Services

A service is a request/response interaction. You ask for something, wait, and get an answer.

Real-world analogy:

  • Topic = Radio broadcast (continuous, one-way)
  • Service = Phone call (you ask, they answer)

When you call a restaurant to make a reservation:

  1. You call (request)
  2. They check availability (processing)
  3. They confirm or deny (response)
  4. Call ends

In ROS2:

Your Node                    Service                      MAVROS
    │                           │                            │
    │──── Request ────────────► │                            │
    │     {value: true}         │ /mavros/cmd/arming         │
    │                           │ ──────────────────────────►│
    │                           │                            │ (arms motors)
    │                           │ ◄──────────────────────────│
    │◄─── Response ───────────  │                            │
    │     {success: true}       │                            │

Key characteristics: - Synchronous — You wait for the response - One-to-one — One client, one server - Blocking — Your code pauses until response arrives - For actions — Do something once, not continuously

When to use services vs topics:

Use Case Use
Arm the drone Service (one-time action)
Change flight mode Service (one-time action)
Get drone position continuously Topic (streaming data)
Send velocity commands Topic (continuous control)

Service commands:

# List all services
ros2 service list

# Check service type
ros2 service type /mavros/cmd/arming

# Call a service from command line
ros2 service call /mavros/cmd/arming mavros_msgs/srv/CommandBool "{value: true}"

Example — arming the drone:

ros2 service call /mavros/cmd/arming mavros_msgs/srv/CommandBool "{value: true}"

Response:

response:
  success: true
  result: 0


Concept 5: Interfaces

Interfaces is the collective term for message types, service types, and action types. They define the "contract" for communication.

Interfaces
├── Messages (.msg)     → Data structure for topics
├── Services (.srv)     → Request/Response structure
└── Actions (.action)   → Goal/Feedback/Result structure (advanced)

Interface commands:

# List all interfaces
ros2 interface list

# Show a message interface
ros2 interface show geometry_msgs/msg/Twist

# Show a service interface
ros2 interface show mavros_msgs/srv/CommandBool

Service interface example:

ros2 interface show mavros_msgs/srv/CommandBool

Output:

bool value
---
bool success
uint8 result

The --- separates request (above) from response (below).

  • Request: value (true = arm, false = disarm)
  • Response: success (did it work?) and result (error code)

Concept 6: Actions (Brief Overview)

Actions are for long-running tasks with feedback. We won't use them directly in Phase 2, but you should know they exist.

Example: "Navigate to waypoint 5km away" - Takes minutes to complete - You want progress updates (50% there, 75% there...) - You might want to cancel mid-way

Structure: - Goal — What you want (go to position X) - Feedback — Progress updates (currently at position Y) - Result — Final outcome (reached / failed)

We'll use services and topics which are simpler and sufficient for our needs.


Concept Summary

Concept What It Is When to Use Drone Example
Node A program Always — everything is a node MAVROS, your control code
Topic Data stream Continuous data Position, velocity, state
Message Data structure Defines topic content PoseStamped, State
Service Request/response One-time actions Arm, set mode, takeoff
Interface Type definition Understanding data ros2 interface show

ROS2 Workspaces

A workspace is a folder where you develop ROS2 packages. Understanding workspaces prevents many common errors.

Underlay and Overlay

ROS2 uses a layered system:

┌─────────────────────────────────────┐
│           Your Workspace            │  ← Overlay (your code)
│        ~/simtofly_ws/ros2_ws        │
├─────────────────────────────────────┤
│          ROS2 Humble Base           │  ← Underlay (system packages)
│         /opt/ros/humble             │
└─────────────────────────────────────┘

Underlay = Base ROS2 installation - Location: /opt/ros/humble - Contains: Core ROS2, standard messages, tools - You don't modify this

Overlay = Your workspace - Location: ~/simtofly_ws/ros2_ws - Contains: Your packages, custom code - You build and modify here

Why layers? - Keep system packages safe from your experiments - Your packages can override system packages if needed - Multiple workspaces can stack

Source Order Matters

You must source in the correct order:

# 1. First, source the underlay (base ROS2)
source /opt/ros/humble/setup.bash

# 2. Then, source your overlay (your workspace)
source ~/simtofly_ws/ros2_ws/install/setup.bash

If you source in wrong order or forget one, you'll get errors like: - "Package not found" - "Command not found" - Wrong version of package used

Our bashrc setup handles this automatically:

# These lines in ~/.bashrc ensure correct order
source /opt/ros/humble/setup.bash
source ~/simtofly_ws/ros2_ws/install/setup.bash

Workspace Structure

~/simtofly_ws/ros2_ws/
├── src/              ← Your source code goes here
│   └── drone_control/    ← Your package
│       ├── package.xml
│       ├── setup.py
│       └── drone_control/
│           └── your_node.py
├── build/            ← Compiled files (auto-generated)
├── install/          ← Installed packages (auto-generated)
└── log/              ← Build logs (auto-generated)

You only edit files in src/. The other folders are created by colcon build.


Set Up Your Workspace

Let's set up the ROS2 workspace properly.

Create Workspace Structure

cd ~/simtofly_ws/ros2_ws
mkdir -p src

Build Empty Workspace

Even with no packages, verify the build system works:

cd ~/simtofly_ws/ros2_ws
colcon build

Expected output:

Starting >>> (empty workspace)

Summary: 0 packages finished

Source Your Workspace

source ~/simtofly_ws/ros2_ws/install/setup.bash

Add to bashrc for automatic sourcing:

echo "source ~/simtofly_ws/ros2_ws/install/setup.bash" >> ~/.bashrc
source ~/.bashrc

Verify Setup

Open a new terminal and test:

ros2 topic list

If this works without errors, your workspace is configured correctly.


Essential CLI Tools Summary

These commands will be your daily tools:

Node Commands

ros2 node list                    # List running nodes
ros2 node info /node_name         # Node details (publishers, subscribers, services)

Topic Commands

ros2 topic list                   # List all topics
ros2 topic echo /topic_name       # Show live data
ros2 topic info /topic_name       # Show message type, publishers, subscribers
ros2 topic hz /topic_name         # Show publish rate
ros2 topic echo /topic --once     # Show one message and exit

Service Commands

ros2 service list                 # List all services
ros2 service type /service_name   # Show service type
ros2 service call /service_name type "{data}"  # Call a service

Interface Commands

ros2 interface list               # List all message/service types
ros2 interface show type_name     # Show structure of a type

Package Commands

ros2 pkg list                     # List installed packages
ros2 pkg prefix package_name      # Show package install location

Verification Checklist

Before moving on, verify:

  • ros2 --version shows version number
  • Demo talker/listener test passes
  • Understand difference: node, topic, message, service
  • Understand underlay vs overlay workspaces
  • ~/simtofly_ws/ros2_ws/src directory exists
  • colcon build runs without errors
  • ROS2 is sourced in bashrc (new terminal works)

What You Accomplished

  • Understood what ROS2 is and why it matters for drones
  • Installed ROS2 Humble on Ubuntu 22.04
  • Learned core concepts: nodes, topics, messages, services, interfaces
  • Understood workspace structure and underlay/overlay system
  • Set up your ROS2 workspace for drone development
  • Learned essential CLI tools

What's Next

In the next section, we'll install MAVROS — the bridge between ROS2 and ArduPilot. You'll see these concepts come alive with real drone data flowing through topics, and services that arm and control the drone.


Common Questions

Q: What's the difference between ROS and OS?

OS (Operating System): Manages your computer's hardware, files, and processes. Examples: Ubuntu, Windows, macOS.

ROS (Robot Operating System): A middleware framework that helps robot software components communicate. It runs on top of an OS, not instead of it.

You need Ubuntu (OS) installed first, then ROS2 runs as software on Ubuntu.


Q: Why Humble specifically?

ROS2 releases are named alphabetically. Humble is the current LTS (Long Term Support) for Ubuntu 22.04:

ROS2 Version Ubuntu Version Support Until
Humble 22.04 2027
Iron 22.04 2024 (ended)
Jazzy 24.04 2029

Humble is the stable choice for Ubuntu 22.04.


Q: Do I need to understand DDS?

No. DDS (Data Distribution Service) is the underlying communication layer, but ROS2 abstracts it away. You'll never interact with DDS directly for drone work. Think of it like TCP/IP — you use the internet without knowing the protocol details.


Q: Can I use both MAVProxy and ROS2?

Yes! MAVROS connects to SITL, and MAVProxy can connect simultaneously. Useful for debugging: - Monitor in MAVProxy console - Test ROS2 code - See both perspectives


Q: What if I have ROS1 installed?

ROS1 and ROS2 can coexist, but not simultaneously in the same terminal. Don't source both. If you have ROS1, ensure your bashrc only sources ROS2:

# ONLY this line, not any ROS1 sources
source /opt/ros/humble/setup.bash

Q: Why do I need to source setup.bash?

Sourcing sets up environment variables that tell your terminal: - Where ROS2 commands are located - Where to find packages - What libraries to use

Without sourcing, your terminal doesn't know ROS2 exists.


Q: What's colcon?

colcon is the build tool for ROS2 workspaces. It: - Finds all packages in src/ - Compiles them in correct dependency order - Installs them to install/

Similar to make or cmake, but designed for ROS2 multi-package builds.


Troubleshooting

"ros2: command not found"

Cause: ROS2 not sourced

Solution:

source /opt/ros/humble/setup.bash

Then add to bashrc as shown earlier.


"colcon: command not found"

Cause: Development tools not installed

Solution:

sudo apt install python3-colcon-common-extensions -y


Package installation fails with GPG error

Cause: GPG key not added correctly

Solution:

sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
sudo apt update


Demo nodes don't communicate

Cause: Different ROS_DOMAIN_ID or network issues

Solution: 1. Ensure both terminals have same environment (run source ~/.bashrc in both) 2. Check echo $ROS_DOMAIN_ID is same in both (default is empty) 3. Restart both nodes


"Package not found" after building

Cause: Workspace not sourced after build

Solution:

source ~/simtofly_ws/ros2_ws/install/setup.bash

You must re-source after every colcon build.


Multiple ROS versions conflicting

Cause: Both ROS1 and ROS2 sourced, or multiple ROS2 versions

Solution: Check your ~/.bashrc for conflicting source lines:

grep "source.*ros" ~/.bashrc

Keep only:

source /opt/ros/humble/setup.bash
source ~/simtofly_ws/ros2_ws/install/setup.bash


Additional Resources


← Back to Phase 2 Overview | Next: 2.2 MAVROS Setup →