A simulated drone system built with ROS 2 Lyrical on Fedora 44. This project demonstrates core ROS 2 concepts through a multi-node drone simulation with publishers, subscribers, services, actions, custom messages, parameters, and launch files.
/drone/sensors
sensor_node ─────────────────────────────► state_machine_node
(Python) ─────────────────────────────► ground_station_node
/drone/state
│
command_node ──── takeoff/land ──► state_machine_node
(Python) ── goto ─────────► controller_node
/drone/cmd_waypoint (action)
| Node | Language | Description |
|---|---|---|
sensor_node |
Python | Publishes simulated sensor data (altitude, battery, GPS, temperature) at 10Hz |
state_machine_node |
Python | Manages drone state transitions (IDLE, TAKING_OFF, FLYING, etc.) |
controller_node |
Python | Executes movement commands and handles waypoint navigation action |
ground_station_node |
Python | Monitors telemetry and displays a formatted dashboard |
command_node |
Python | CLI tool to send commands (takeoff, land, goto, emergency) |
| Type | Name | Fields |
|---|---|---|
| Message | SensorData |
altitude, battery, latitude, longitude, temperature, voltage |
| Message | DroneState |
state, battery, altitude, latitude, longitude |
| Service | Takeoff |
Request: target_altitude; Response: success, message |
| Service | Land |
Request: confirm; Response: success, message |
| Service | EmergencyStop |
Request: reason; Response: success, message |
| Action | GoToWaypoint |
Goal: latitude, longitude, altitude; Feedback: current_lat/lng/alt, distance_remaining; Result: success, message |
- Fedora 44 (KDE Plasma or other desktop)
- ROS 2 Lyrical desktop (installed via COPR, includes
ros2CLI and dev tools) - GCC/G++ compiler
- Python 3.10+
# Enable the COPR repository (flagship for Fedora 44)
sudo dnf copr enable hellaenergy/ros2
# Install ROS 2 desktop (includes ros2 CLI, launch, demo nodes, rqt)
sudo dnf install ros-lyrical-ros-desktop
# Install interface generators (required for custom .msg/.srv/.action)
sudo dnf install ros-lyrical-rosidl-default-generators ros-lyrical-rosidl-default-runtime
# Source ROS 2 (add to ~/.bashrc for persistence)
echo "source /opt/ros/lyrical/setup.bash" >> ~/.bashrc
source /opt/ros/lyrical/setup.bashsudo dnf install -y gcc-c++ cmake python3-colcon-common-extensions python3-rosdep# Check ROS 2 is working
ros2 --help
# Run the talker/listener demo to verify
# Terminal 1:
ros2 run demo_nodes_cpp talker
# Terminal 2:
ros2 run demo_nodes_py listener# Clone the repository
git clone https://github.com/Je0Dev/ros2-tutorial-drones.git
cd ros2-tutorial-drones
# Build drone_interfaces first (custom interfaces must be built before drone_system)
colcon build --packages-select drone_interfaces
source install/setup.bash
# Build drone_system (Python nodes)
colcon build --packages-select drone_system
source install/setup.bash
# Fix ros2 run: create wrapper scripts (required due to missing ament_python in Lyrical)
chmod +x install/drone_system/lib/drone_system/* 2>/dev/nullNote:
ros2 launchis not available in this Lyrical build. Use the wrapper script instead:
./build.sh # builds and creates ros2 run wrappers
# Then run individual nodes in separate terminals (see below)# Terminal 1: Sensor data
ros2 run drone_system sensor_node
# Terminal 2: State machine
ros2 run drone_system state_machine_node
# Terminal 3: Controller
ros2 run drone_system controller_node
# Terminal 4: Ground station monitor
ros2 run drone_system ground_station_node# Takeoff to 10 meters
ros2 run drone_system command_node takeoff 10.0
# Navigate to a waypoint
ros2 run drone_system command_node goto 37.7749 -122.4194 15.0
# Land
ros2 run drone_system command_node land
# Emergency stop
ros2 run drone_system command_node emergency "Low battery"ros2 node list
ros2 topic list
ros2 service list
ros2 action listros2-tutorial/
├── README.md
├── LICENSE # Apache 2.0
├── CONTRIBUTING.md
├── AGENTS.md # AI agent instructions
├── CONSTRAINTS.md # Safety guardrails
├── .gitignore
└── src/
├── drone_interfaces/ # Custom message, service, action definitions
│ ├── msg/
│ ├── srv/
│ ├── action/
│ ├── CMakeLists.txt
│ └── package.xml
└── drone_system/ # All node implementations (Python)
├── drone_system/ # Python nodes
├── launch/ # Launch files
├── config/ # Parameter files
├── test/ # Tests
├── setup.py
└── package.xml
| Concept | Implementation |
|---|---|
| Publishers | sensor_node publishes SensorData on /drone/sensors |
| Subscribers | state_machine_node, ground_station_node subscribe to topics |
| Services | Takeoff, Land, EmergencyStop service servers |
| Actions | GoToWaypoint action server in controller_node |
| Custom Messages | SensorData, DroneState |
| Custom Services | Takeoff, Land, EmergencyStop |
| Custom Actions | GoToWaypoint |
| Parameters | battery_warn_threshold, max_altitude, sensor_rate, etc. |
| TimerCallbacks | sensor_node uses timers for periodic publishing |
Parameters are defined in src/drone_system/config/params.yaml:
sensor_node:
ros__parameters:
sensor_rate: 10.0
initial_altitude: 0.0
initial_battery: 100.0
battery_drain_rate: 0.1
state_machine_node:
ros__parameters:
battery_warn_threshold: 20.0
battery_critical_threshold: 10.0
max_altitude: 120.0This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
See CONTRIBUTING.md for guidelines on how to contribute.