Skip to main content
🤝

이 가이드는 인류와 AI가 함께 만드는 지식입니다.

이 콘텐츠는 Human + AI Partnership 철학 아래 모든 사람이 로봇·AI를 배울 수 있도록 무료로 제공됩니다. 당신의 질문과 기여가 다음 학생의 미래를 바꿉니다.

ROS 2 Drone & Aerial Vehicles Guide 2026

Autonomous drones bridge a flight controller (PX4/ArduPilot) with a companion computer running ROS 2. This guide covers offboard control, mission planning, visual-inertial odometry for GPS-denied flight, obstacle avoidance, and multi-drone swarms.

Regulatory note: Autonomous flight is regulated (FAA Part 107, EASA, local rules). Test in simulation or approved areas, respect airspace and line-of-sight rules, and keep a manual override ready.

1. The Drone Autonomy Stack

A flight controller handles stabilization; ROS 2 on a companion computer handles autonomy:

# PX4 + ROS 2 via micro-ROS / uXRCE-DDS (modern bridge)
# On the companion computer (Jetson / RPi):
ros2 run micro_ros_agent micro_ros_agent   udp4 --port 8888

# Legacy option: MAVROS (MAVLink <-> ROS bridge)
sudo apt-get install -y ros-humble-mavros ros-humble-mavros-extras
ros2 launch mavros px4.launch fcu_url:=/dev/ttyUSB0:921600

# Layers:
#   1. Flight controller  (PX4/ArduPilot — attitude + position hold)
#   2. Bridge             (uXRCE-DDS or MAVROS)
#   3. State estimation    (EKF2 / VIO for GPS-denied)
#   4. Autonomy            (missions, avoidance, swarm)

2. Offboard Control

Offboard mode lets ROS 2 stream setpoints to PX4. You must stream continuously or PX4 fails safe:

from px4_msgs.msg import OffboardControlMode, TrajectorySetpoint, VehicleCommand

class OffboardControl(Node):
    def __init__(self):
        super().__init__('offboard_control')
        self.mode_pub = self.create_publisher(OffboardControlMode,
            '/fmu/in/offboard_control_mode', 10)
        self.sp_pub = self.create_publisher(TrajectorySetpoint,
            '/fmu/in/trajectory_setpoint', 10)
        # 10 Hz heartbeat is MANDATORY — gaps trigger failsafe
        self.create_timer(0.1, self.loop)

    def loop(self):
        mode = OffboardControlMode(); mode.position = True
        self.mode_pub.publish(mode)

        sp = TrajectorySetpoint()
        sp.position = [0.0, 0.0, -5.0]   # NED: -5 = 5m altitude
        sp.yaw = 0.0
        self.sp_pub.publish(sp)

3. Arming & Takeoff Sequence

Enter offboard mode, arm, then command position. Order matters:

def arm_and_takeoff(self):
    # 1. Stream setpoints BEFORE switching to offboard (PX4 requires it)
    for _ in range(20):
        self.publish_setpoint(0, 0, -5)
        sleep(0.05)
    # 2. Switch to offboard
    self.send_command(VehicleCommand.VEHICLE_CMD_DO_SET_MODE, 1.0, 6.0)
    # 3. Arm
    self.send_command(VehicleCommand.VEHICLE_CMD_COMPONENT_ARM_DISARM, 1.0)
    # 4. Keep streaming the climb setpoint — the drone ascends to 5m

4. Mission Planning

For waypoint missions, either upload a MAVLink mission or stream trajectory setpoints:

waypoints = [
    (0.0,  0.0, -5.0),
    (10.0, 0.0, -5.0),
    (10.0, 10.0, -8.0),
    (0.0,  10.0, -5.0),
    (0.0,  0.0, -5.0),
]

def fly_mission(self, waypoints, tol=0.5):
    for wp in waypoints:
        while distance(self.position, wp) > tol:
            self.publish_setpoint(*wp)
            sleep(0.05)
        self.get_logger().info(f'Reached {wp}')

5. GPS-Denied Flight: Visual-Inertial Odometry

Indoors or under bridges, feed VIO pose into PX4 as an external estimate:

# Run VINS-Fusion or a RealSense T265 for VIO, then feed PX4:
ros2 run vio_bridge vio_to_px4   --ros-args   -r vio_pose:=/camera/pose/sample   -r px4_vision:=/fmu/in/vehicle_visual_odometry

# In PX4 params set:
#   EKF2_EV_CTRL   = enable external vision position + yaw
#   EKF2_GPS_CTRL  = 0   (disable GPS indoors)
# The EKF2 now fuses VIO instead of GPS for position hold.

6. Obstacle Avoidance

Use a depth camera to build a local map and deflect setpoints around obstacles:

def avoid(self, goal_setpoint, depth_cloud):
    # Repulsive vector from nearby points (potential fields)
    repulse = np.zeros(3)
    for pt in downsample(depth_cloud):
        d = np.linalg.norm(pt)
        if d < SAFE_DIST:
            repulse -= (pt / d) * (SAFE_DIST - d) * K_REP
    attract = (goal_setpoint - self.position) * K_ATT
    return self.position + normalize(attract + repulse) * STEP
    # PX4's collision prevention (CP_DIST) is a second safety layer

7. Drone Swarms

Coordinate many drones with per-drone namespaces and DDS partitions:

# Launch N drones, each isolated by ROS_DOMAIN_ID / namespace
for i in range(swarm_size):
    Node(package='offboard_control', executable='offboard',
         namespace=f'drone{i}',
         parameters=[{'system_id': i + 1}])

# Formation control: each drone holds an offset from the leader
def formation_setpoint(self, leader_pose, offset):
    return leader_pose.position + rotate(offset, leader_pose.yaw)
# Consensus + collision avoidance keep the swarm cohesive and safe.

8. Simulation with Gazebo

# PX4 SITL (software-in-the-loop) + Gazebo — no hardware needed
make px4_sitl gz_x500

# Connect ROS 2 and fly the same code as on hardware:
ros2 run micro_ros_agent micro_ros_agent udp4 --port 8888
ros2 run offboard_control offboard
# Always prove missions in SITL before any real flight.

9. Safety & Failsafes

10. Applications

Key Takeaways

Autonomous drones split work between a PX4/ArduPilot flight controller and a ROS 2 companion computer over the uXRCE-DDS bridge. Offboard mode needs a continuous setpoint heartbeat, VIO enables GPS-denied flight, and potential-field avoidance keeps the aircraft clear of obstacles. Coordinate swarms with namespaces and formation control, prove everything in PX4 SITL + Gazebo first, and treat RC override, RTL, and geofencing as non-negotiable failsafes.