ROS 2 - Basic Programming & Practice
Autonomous drone flight control system using ROS 2, featuring PID controllers and waypoint navigation.
RoboticsROS2
# features
Key Features
Core technologies and system features.
PID Control
Implementation of PID controllers for stable drone flight.
Waypoint Navigation
Automated flight paths through predefined coordinate markers.
ROS 2 Integration
Built using ROS 2 for modular robotics software.
# source
Project Source Code
Explore the primary logical modules.
EXPLORER
srcbeta_pilot_controller_node.py
1import rclpy2from rclpy.node import Node3import math4from rclpy.qos import QoSProfile56from sfr_coursework1_interface_package.msg import WheelAngularVelocities, TaskSpacePose7from sfr_coursework1_interface_package.srv import TurnRobotOn, TurnRobotOff8910class ControllerNode(Node):11 def __init__(self):12 super().__init__("controller_node")1314 # Assigned from coursework spreadsheet15 self.desired_angle_deg = 124.016 self.desired_angle_rad = math.radians(self.desired_angle_deg)1718 # Robot physical parameters19 self.r = 0.0920 self.l = 0.282122 # Robot state23 self.current_phi = 0.024 self.current_x = 0.025 self.current_y = 0.02627 self.rotation_done = False28 self.translation_done = False2930 self.start_x = None31 self.start_y = None3233 qos = QoSProfile(depth=10)3435 # Publisher for wheel angular velocities36 self.pub = self.create_publisher(37 WheelAngularVelocities,38 "robot/wheel_angular_velocities",39 qos40 )4142 # Subscriber for pose feedback43 self.create_subscription(44 TaskSpacePose,45 "robot/task_space_pose",46 self.pose_callback,47 qos48 )4950 # Service clients51 self.on_client = self.create_client(TurnRobotOn, "robot/turn_robot_on")52 self.off_client = self.create_client(TurnRobotOff, "robot/turn_robot_off")5354 self.wait_for_services()55 self.turn_robot_on()5657 # Control loop timer58 self.timer = self.create_timer(0.1, self.control_loop)5960 self.get_logger().info(f"Controller node started. Target angle = {self.desired_angle_deg}°")616263 # -------------------------------------------------------64 def wait_for_services(self):65 while not self.on_client.wait_for_service(timeout_sec=1.0):66 self.get_logger().info("Waiting for turn_robot_on service...")6768 while not self.off_client.wait_for_service(timeout_sec=1.0):69 self.get_logger().info("Waiting for turn_robot_off service...")707172 # -------------------------------------------------------73 def turn_robot_on(self):74 req = TurnRobotOn.Request()75 future = self.on_client.call_async(req)76 rclpy.spin_until_future_complete(self, future)77 self.get_logger().info("Robot turned ON by controller.")787980 def turn_robot_off(self):81 req = TurnRobotOff.Request()82 future = self.off_client.call_async(req)83 rclpy.spin_until_future_complete(self, future)84 self.get_logger().info("Robot turned OFF by controller.")858687 # -------------------------------------------------------88 def pose_callback(self, msg):89 self.current_x = msg.x90 self.current_y = msg.y91 self.current_phi = msg.phi_z929394 # -------------------------------------------------------95 def control_loop(self):9697 # ============================98 # PHASE 1 — ROTATE ROBOT99 # ============================100 if not self.rotation_done:101102 self.get_logger().info(103 f"Rotating robot toward {self.desired_angle_deg} degrees... (current={math.degrees(self.current_phi):.2f})"104 )105106 if self.current_phi >= self.desired_angle_rad:107 # STOP rotation108 msg = WheelAngularVelocities()109 msg.left_wheel_angular_velocity = 0.0110 msg.right_wheel_angular_velocity = 0.0111 self.pub.publish(msg)112113 self.rotation_done = True114 self.start_x = self.current_x115 self.start_y = self.current_y116117 self.get_logger().info("Rotation complete. Starting translation forward 1 meter.")118 return119120 # Continue rotating121 omega = 0.5 # rad/s rotation speed122 v_r = (self.l * omega) / 2123 v_l = -v_r124125 msg = WheelAngularVelocities()126 msg.left_wheel_angular_velocity = v_l / self.r127 msg.right_wheel_angular_velocity = v_r / self.r128 self.pub.publish(msg)129 return130131 # ============================132 # PHASE 2 — MOVE FORWARD 1 METER133 # ============================134 if not self.translation_done:135136 dx = self.current_x - self.start_x137 dy = self.current_y - self.start_y138 distance = math.sqrt(dx*dx + dy*dy)139140 self.get_logger().info(f"Moving forward... Distance = {distance:.3f} m")141142 if distance >= 1.0:143 # STOP144 msg = WheelAngularVelocities()145 msg.left_wheel_angular_velocity = 0.0146 msg.right_wheel_angular_velocity = 0.0147 self.pub.publish(msg)148149 self.get_logger().info("Target distance achieved (1.000 m). Stopping robot.")150151 self.translation_done = True152 self.turn_robot_off()153 self.get_logger().info("Translation complete. Controller stopping.")154 self.destroy_timer(self.timer)155 return156157 # Continue straight motion158 v = 0.1 # m/s159160 msg = WheelAngularVelocities()161 msg.left_wheel_angular_velocity = v / self.r162 msg.right_wheel_angular_velocity = v / self.r163 self.pub.publish(msg)164165166# -------------------------------------------------------167def main(args=None):168 rclpy.init(args=args)169 node = ControllerNode()170171 try:172 rclpy.spin(node)173 except KeyboardInterrupt:174 node.get_logger().info("Keyboard interrupt received. Shutting down cleanly.")175176177178if __name__ == "__main__":179 main()180# simulation
Simulation Video
Integrated video walkthrough of the autonomous flight system.
simulation
0:00 / 0:00
# repositories
Source Code
GitHub repositories for this project.