5.1 KiB
5.1 KiB
DroneController Guide (GPS-Denied)
Implement your landing algorithm in drone_controller.py.
Quick Start
- Edit
drone_controller.py - Find
calculate_landing_maneuver() - Implement your algorithm
- Test with any mode:
python standalone_simulation.py --pattern stationary(standalone)python run_bridge.py --pattern stationary(PyBullet + ROS 2)python run_gazebo.py --pattern stationary(Gazebo + ROS 2)
GPS-Denied Challenge
No GPS available. You must use:
| Sensor | Data |
|---|---|
| IMU | Orientation, angular velocity |
| Altimeter | Altitude, vertical velocity |
| Velocity | Estimated from optical flow |
| Camera | 320x240 downward image (base64 JPEG) |
| Landing Pad | Relative position (may be null!) |
Function to Implement
def calculate_landing_maneuver(self, telemetry, rover_telemetry):
# Your code here
return (thrust, pitch, roll, yaw)
Sensor Data
IMU
imu = telemetry['imu']
roll = imu['orientation']['roll']
pitch = imu['orientation']['pitch']
yaw = imu['orientation']['yaw']
angular_vel = imu['angular_velocity'] # {x, y, z}
Altimeter
altimeter = telemetry['altimeter']
altitude = altimeter['altitude']
vertical_vel = altimeter['vertical_velocity']
Velocity
velocity = telemetry['velocity'] # {x, y, z} in m/s
Camera
The drone has a downward-facing camera providing 320x240 JPEG images.
import base64
from PIL import Image
import io
camera = telemetry['camera']
image_b64 = camera.get('image')
if image_b64:
image_bytes = base64.b64decode(image_b64)
image = Image.open(io.BytesIO(image_bytes))
# Process image for custom vision algorithms
Landing Pad (Vision)
Important: May be None if pad not visible!
landing_pad = telemetry['landing_pad']
if landing_pad is not None:
relative_x = landing_pad['relative_x'] # body frame
relative_y = landing_pad['relative_y'] # body frame
distance = landing_pad['distance'] # vertical
confidence = landing_pad['confidence'] # 0-1
Control Output
| Value | Range | Effect |
|---|---|---|
| thrust | ±1.0 | Up/down |
| pitch | ±0.5 | Forward/back |
| roll | ±0.5 | Left/right |
| yaw | ±0.5 | Rotation |
Example Algorithm
def calculate_landing_maneuver(self, telemetry, rover_telemetry):
altimeter = telemetry.get('altimeter', {})
altitude = altimeter.get('altitude', 5.0)
vertical_vel = altimeter.get('vertical_velocity', 0.0)
velocity = telemetry.get('velocity', {})
vel_x = velocity.get('x', 0.0)
vel_y = velocity.get('y', 0.0)
landing_pad = telemetry.get('landing_pad')
# Altitude control
thrust = 0.5 * (0 - altitude) - 0.3 * vertical_vel
# Horizontal control
if landing_pad is not None:
pitch = 0.3 * landing_pad['relative_x'] - 0.2 * vel_x
roll = 0.3 * landing_pad['relative_y'] - 0.2 * vel_y
else:
pitch = -0.2 * vel_x
roll = -0.2 * vel_y
return (thrust, pitch, roll, 0.0)
Using the Camera
You can implement custom vision processing on the camera image:
import cv2
import numpy as np
import base64
def process_camera(telemetry):
camera = telemetry.get('camera', {})
image_b64 = camera.get('image')
if not image_b64:
return None
# Decode JPEG
image_bytes = base64.b64decode(image_b64)
nparr = np.frombuffer(image_bytes, np.uint8)
image = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
# Example: detect green landing pad
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
green_mask = cv2.inRange(hsv, (35, 50, 50), (85, 255, 255))
# Find contours
contours, _ = cv2.findContours(green_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
largest = max(contours, key=cv2.contourArea)
M = cv2.moments(largest)
if M['m00'] > 0:
cx = int(M['m10'] / M['m00'])
cy = int(M['m01'] / M['m00'])
# cx, cy is center of detected pad in image coordinates
return (cx, cy)
return None
Strategies
When Pad Not Visible
- Maintain altitude and stabilize
- Search by ascending or spiraling
- Dead reckoning from last known position
State Machine
- Search → find pad
- Approach → move above pad
- Align → center over pad
- Descend → controlled descent
- Land → touch down
Testing
# Easy - stationary rover
python standalone_simulation.py --pattern stationary
# Medium - slow circular movement
python standalone_simulation.py --pattern circular --speed 0.2
# Hard - faster random movement
python standalone_simulation.py --pattern random --speed 0.3
# With ROS 2 (Gazebo)
ros2 launch gazebo/launch/drone_landing.launch.py # Terminal 1
python run_gazebo.py --pattern circular # Terminal 2
Configuration
Edit config.py to tune controller gains:
CONTROLLER = {
"Kp_z": 0.5, # Altitude proportional gain
"Kd_z": 0.3, # Altitude derivative gain
"Kp_xy": 0.3, # Horizontal proportional gain
"Kd_xy": 0.2, # Horizontal derivative gain
}