Skip to content

Latest commit

 

History

37 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

IMAV 2023 Indoor Competition — Black Bee Drones

3rd Place, Indoor Challenge · the only team to complete the course fully autonomously.

This repository holds the indoor navigation code that Black Bee Drones flew at the International Micro Air Vehicle Conference and Competition (IMAV 2023), hosted by RWTH Aachen University, Germany.

Heads up — this is ROS 1 (Noetic) code. It depends on the team's first-generation SDK, tadinisdk. The team's current ROS 2 SDK, nectar-sdk, is a separate, later stack and is not compatible with this package.

Competition Video

drone_line_following_video.mp4

Drone executing the autonomous line-following mission during IMAV 2023.

Competition Overview

The indoor challenge was a payload-transport task. The arena had a takeoff zone, a set of pickup blocks identified by ArUco markers, several transit routes marked by colored ropes, and a drop zone. A run consisted of taking off, landing on a pickup marker to attach a cone, following a transit route to the drop zone, and releasing the cone.

Both the pickup block and the transit route came in variants of increasing difficulty:

Pickup block Transit route
Unobstructed — marker flat on the floor Free — open rope, no obstacles
Obstructed — marker under a 1 m obstacle Gate — 1×1 m gate to fly through
Rotating — marker on a turntable Moving gate — 2×1 m gate with a moving obstacle
Cooperative — cone carried by 2–3 drones together

This repository implements the baseline run: the unobstructed block and the free transit route. The other variants were out of scope for the code published here.

Technical Stack

Hardware

  • Companion computer: Raspberry Pi (runs the camera and pose bridge onboard)
  • Pose/odometry: Intel RealSense T265 visual-inertial tracking camera, feeding ArduPilot through vision_to_mavros
  • Vision camera: Raspberry Pi Camera v2 (down-facing), used for line and marker detection
  • Flight controller: ArduPilot-based controller, EKF3, commanded over MAVLink/MAVROS
  • Payload: servo-actuated gripper to attach and release the cone

Software

  • ROS 1 Noetic — middleware
  • MAVROS — ROS ↔ ArduPilot bridge
  • tadinisdk — team SDK: drone control, color detection, ArUco detection, PID wrapper
  • vision_to_mavros — T265 pose → MAVROS vision pose
  • SMACH — state-machine framework for mission orchestration
  • OpenCV — image processing and line approximation
  • ros pid — PID control loops (wrapped by tadinisdk)

System Architecture

The mission is built from three components that can each run on their own: line following, ArUco centering, and a state machine that sequences them. Detection and control are split into separate nodes that communicate over ROS topics, so control gains can be tuned live (via rqt_reconfigure) without restarting detection.

Mission State Machine

state_machine.py (launched by mangalarga.launch) runs the full baseline course:

stateDiagram-v2
    [*] --> SEARCH_ARUCO_PICK_UP_ZONE
    SEARCH_ARUCO_PICK_UP_ZONE --> FOLLOW_ARUCO_PICK_UP_ZONE: marker 200 found
    FOLLOW_ARUCO_PICK_UP_ZONE --> LAND: centered
    LAND --> SEARCH_ARUCO_TRANSIT_ZONE: cone attached
    SEARCH_ARUCO_TRANSIT_ZONE --> FOLLOW_ARUCO_TRANSIT_ZONE: marker 600 found
    FOLLOW_ARUCO_TRANSIT_ZONE --> FOLLOW_LINE: centered
    FOLLOW_LINE --> DROP_ZONE: line ended
    DROP_ZONE --> [*]: cone released
Loading
State Action
SEARCH_ARUCO_PICK_UP_ZONE Arm, take off to 1.35 m, fly forward at 0.12 m/s until the pickup marker (ID 200) is seen in 15 frames.
FOLLOW_ARUCO_PICK_UP_ZONE Center over the marker with the ArUco controller.
LAND Land on the marker, drive the gripper servo to grab the cone, wait for operator confirmation.
SEARCH_ARUCO_TRANSIT_ZONE Take off again and search for the transit-route marker (ID 600).
FOLLOW_ARUCO_TRANSIT_ZONE Center over the transit marker.
FOLLOW_LINE Descend to ~0.70 m, then follow the colored rope until the line ends (no detection for 5 s).
DROP_ZONE Move forward briefly, land, release the gripper servo to drop the cone.

Component 1 — Follow Line

Keeps the drone centered over a colored rope and aligned with its direction while flying forward. Detection and control are two nodes.

Detection (line_detection_node.pyLineDetector.py):

  1. Resize the camera frame to 640×480 and color-filter it for line_color (tadinisdk color detector).
  2. Restrict processing to a 600×130 px band centered in the frame.
  3. Fit a line to the mask and extract its horizontal center (px) and angle (deg). Default method is a probabilistic Hough transform + cv2.fitLine; LineDetector.py also includes min-area-rectangle and ellipse-fit alternatives.
  4. Publish center_x and angle on line_state (LineInfo.msg).

Control (follow_line_node.py):

  • Constant forward speed: 0.12 m/s.
  • Lateral velocity from a PID on center_xKp=-0.00042, Ki=-0.00005, Kd=0, setpoint = 320 (image center).
  • Yaw rate from a PID on angleKp=0.0078, Ki=0, Kd=0, setpoint = 0.
  • Small efforts are ignored (dead-bands of 0.025 m/s lateral, 0.1 rad/s yaw) to avoid jitter.
  • The line is considered finished after 5 s without a detection, which ends the state.

Run it:

# detection only
roslaunch indoor line_detect.launch line_color:=red image_source:=/raspicam_node/image/compressed

# detection + control
roslaunch indoor follow_line.launch line_color:=red drone:=mavros image_source:=/raspicam_node/image/compressed plot:=false

Component 2 — Follow ArUco

Centers the drone directly over an ArUco marker, used to locate the pickup block, the transit route, and the drop zone.

Detection: tadinisdk ArUco node publishes the marker pose relative to the camera.

Control (aruco_control_node.py): two PID loops, one per horizontal axis, drive the drone until the marker is centered under the camera (each loop tracks one component of the marker's relative position with setpoint 0):

  • vel_x PID — Kp=-0.34, Ki=-0.02, Kd=0
  • vel_y PID — Kp=-0.42, Ki=-0.024, Kd=0
  • Efforts below 0.03 m/s are ignored; once 15 frames have both efforts below threshold, the drone is reported "centered".

Run it:

roslaunch indoor aruco_centralize.launch image_source:=/raspicam_node/image/compressed drone:=mavros marker_dict:=5 tag_size:=0.15

Component 3 — State Machine

state_machine.py wires the components above into the full run (see the diagram and table in System Architecture). The detection/control nodes run in the background and the state machine activates each one over its control_activation topic, waiting for the matching "done" signal before transitioning.

Run the full mission:

roslaunch indoor mangalarga.launch drone:=mavros line_color:=red image_source:=/raspicam_node/image/compressed marker_dict:=5 tag_size:=0.15 plot:=false

Launch Parameters

These are shared by the launch files above:

Parameter Default Description
image_source /raspicam_node/image/compressed webcam, or a ROS Image/CompressedImage topic. For the Pi camera the launch starts raspicam_node automatically.
drone mavros Control backend: mavros (ArduPilot) or bebop. For mavros, the MAVROS apm.launch must already be running.
line_color red Color name saved during color calibration (see below).
marker_dict 5 ArUco dictionary cell count.
tag_size 0.15 ArUco marker side length, in meters.
plot false Open rqt_reconfigure to tune PID gains live.

Setup

Prerequisites (on the Raspberry Pi)

  1. Base Raspberry Pi + ROS Noetic setup.
  2. Intel RealSense SDK 2.0 (v2.53.1).
  3. realsense-ros (ros1-legacy).
  4. raspicam_node for the Pi camera.
  5. SMACH: sudo apt-get install ros-noetic-smach-ros.

Build

cd ~/catkin_ws/src

# Team SDK (provides control, color/ArUco detection, PID wrapper)
git clone https://github.com/Black-Bee-Drones/tadinisdk.git

# This package
git clone https://github.com/Black-Bee-Drones/imav2023-indoor.git

cd ~/catkin_ws
catkin_make
source devel/setup.bash

Tip: running the heavy nodes on a laptop while the Pi handles only the RealSense and camera noticeably improved flight time during testing.

Bring-up order

# 1. T265 pose bridge to ArduPilot (set the EKF origin, then climb ~1 m to initialize height)
roslaunch vision_to_mavros t265_all_nodes.launch

# 2. Pi camera
roslaunch raspicam_node camerav2_410x308_30fps.launch

Color calibration

Before flying the line follower, calibrate the rope color:

roslaunch tadinisdk color_calibrate.launch image_source:=/raspicam_node/image/compressed

Press s over the window and enter a color name to save it; use that name as line_color.

Repository Structure

indoor/
├── launch/
│   ├── mangalarga.launch          # Full mission: state machine + line + aruco
│   ├── follow_line.launch         # Line detection + line controller
│   ├── line_detect.launch         # Line detection only
│   └── aruco_centralize.launch    # ArUco detection + aruco controller
├── msg/
│   └── LineInfo.msg               # center_x (px), angle (deg)
├── src/
│   ├── state_machine.py           # SMACH mission orchestration
│   ├── follow_line/
│   │   ├── LineDetector.py        # Color filter + line approximation (OpenCV)
│   │   ├── line_detection_node.py # Publishes line_state (LineInfo)
│   │   └── follow_line_node.py    # PID lateral + yaw, constant forward speed
│   └── aruco_control/
│       └── aruco_control_node.py  # PID centering over an ArUco marker
├── CMakeLists.txt
└── package.xml

Related Repositories

Repository Role
tadinisdk ROS 1 SDK this package is built on (control, detection, PID).
vision_to_mavros T265 pose → MAVROS vision pose bridge.
pid-controller Standalone ROS 2 PID node (modern equivalent of the ROS 1 pid used here).
nectar-sdk The team's current ROS 2 SDK (this code predates it).

References

Team

Black Bee Drones — Federal University of Itajubá (UNIFEI), Brazil. Latin America's first academic autonomous drone team.

About

14th anual International Micro Air Vehicle Conference and Competition (IMAV 2023 - Indoor)

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages