UAV Control and Swarming
Cascaded PID-based control and swarm motion of drones — our solution to the Drona Aviation Pluto Swarm Challenge at Inter IIT Tech Meet 11.0.
This is our solution for the Drona Aviation Pluto Swarm Challenge at Inter IIT Tech Meet 11.0. It comprises the following three tasks:
- Task 1 — Create a Python wrapper for the drone that enables users to control it without using the mobile application.
- Task 2 — Use ArUco markers and an overhead camera to localize the drone. Implement a PID controller to hover it at a constant position and move it in a rectangular path.
- Task 3 — Create a swarm of two drones where one drone follows the other autonomously in a 1×2 m rectangular trajectory.
Task 1 — Python Wrapper
The Python wrapper is built upon the Pluto ROS package provided as a reference. It begins an instant connection with the drone by initiating a class that relies on multithreading and TCP communication to maintain continuous communication with the drone. Transmission occurs using the MultiWii Serial Protocol (MSP), encoded and decoded in the reader and writer files.
Task 2 — Localization and Control
The drone hovers at a position and moves in a 1×2 m rectangle while maintaining a certain height. The requirements are:
- Localization: pose estimation of an ArUco marker
- Controls: PID for position and height control
- Trajectory: defines the path for the drone
We used a Logitech BRIO 4K camera (1080p, 60 fps) and a 45×45 mm, 4×4-bit ArUco marker (ID 0).
Localization
The pose-estimation process is as follows:
- Calibrate the camera to compute its intrinsic matrix and distortion coefficients.
- Detect the markers using OpenCV’s ArUco library.
- Transform the point to the camera’s coordinate frame by computing the extrinsic matrix via
solvePnP(). - Correct the noisy height estimate using machine learning to make readings accurate enough for optimal height control.
The classical method gave accurate x and y positions, but height estimates were only satisfactory near the center of the camera’s FOV and quite erroneous near the boundaries. To improve accuracy, we brought machine learning into the picture.
Pose Correction using Machine Learning
For height correction, we prepared our own dataset using a Time-of-Flight (ToF) sensor and applied linear regression on the transformed pose to predict the drone’s height precisely. For better tolerance against noise and fluctuation, we introduced a Kalman Filter that fuses the current IMU acceleration with the regression-based pose estimate to provide the final pose to the controller. Other than smoothing data, it also guards against failure cases such as the camera failing to localize the drone.
Control
PID controls movement in the x, y, and z directions, estimating roll, pitch, and thrust to achieve the desired coordinates. Any change in the pitch and roll changes the direction of the thrust force, causing erroneous movement; to counter this, the component of thrust along the z-direction is taken, and the drone’s coordinate system is transformed into the camera’s frame using yaw values. We used trackbars to dynamically tune PID values and matplotlib to continuously visualize the system’s state and target.
Trajectory
To move the drone in a 1×2 m rectangle, we wrote a function that returns a list of waypoints, with all movement controlled by PID. The path is broken into chunks; a function continuously checks whether the next checkpoint has been reached by comparing it with the drone’s current coordinates, then updates the step and next coordinate until the final destination is reached.
Task 3 — Swarming
Task 3 asked us to control a follower drone that traces a similar path to the primary drone from Task 2. Our solution was to use multi-UAV flocking algorithms to achieve accurate following. The three simple rules, in the context of our task, are:
- Alignment — the follower attempts to move in the average velocity direction of the primary drone.
- Cohesion — the follower attempts to move toward the average position of the primary drone.
- Separation — the follower attempts to move away if it gets too close to the primary drone.
Alignment
align(self, target):
desiredVelocity = target.Velocity()
steerForce = Vector.sub(desiredVelocity, currentVelocity)
steerForce.limit(maxforce)
self.applyForce(steerForce)
Cohesion
cohesion(self, target):
relPosition = target.Position() - self.Position()
steerForce = Vector.sub(relPosition, target.Velocity())
steerForce.limit(maxforce)
self.applyForce(steerForce)
Separation
separation(self, target):
relPosition = target.Position() - self.Position()
distance = relPosition.Magnitude()
if distance < threshold:
steerForce = -1 * relPosition
steerForce.limit(maxforce)
self.applyForce(steerForce)
Implementation
The entire algorithm was compiled into a simulation using PyBullet and a Gym environment. Due to time and hardware constraints, we could not transform the simulation into a hardware implementation; however, we achieved a highly accurate path-following algorithm that precisely guides the follower drone along the correct trajectory.