Docs Update

This commit is contained in:
2026-01-04 01:42:01 +00:00
parent 40286fa90c
commit edfed30fb1
9 changed files with 591 additions and 305 deletions

1
.gitignore vendored
View File

@@ -1,5 +1,4 @@
venv/
__pycache__/
notes/

View File

@@ -1,10 +1,10 @@
# Drone Landing Simulation (GPS-Denied)
Land a drone on a moving platform using only relative sensors (IMU, altimeter, camera).
Land a drone on a moving platform using only relative sensors.
## Quick Start
### Standalone (1 Terminal - Any Platform)
### Standalone (1 Terminal)
```bash
source activate.sh
@@ -22,30 +22,31 @@ ros2 launch gazebo/launch/drone_landing.launch.py
```bash
source activate.sh
python run_gazebo.py --pattern circular
python camera_viewer.py # View camera
```
### ArduPilot SITL (2 Terminals)
### ArduPilot GPS-Denied (2 Terminals)
**Terminal 1:**
```bash
gz sim -v4 -r ~/ardupilot_gazebo/worlds/iris_runway.sdf
./scripts/run_ardupilot_sim.sh camera
```
**Terminal 2:**
```bash
sim_vehicle.py -v ArduCopter -f gazebo-iris --model JSON --console
# GPS-denied mode:
param set ARMING_CHECK 0
mode stabilize
arm throttle force
```
## Installation
```bash
# Ubuntu/Debian
./setup/install_ubuntu.sh
# ArduPilot SITL (optional)
./setup/install_ardupilot.sh
# Activate environment
./setup/install_ardupilot.sh # Optional
source activate.sh
```
@@ -55,31 +56,30 @@ source activate.sh
|------|-------------|
| `standalone_simulation.py` | All-in-one simulation |
| `run_gazebo.py` | Gazebo controllers |
| `scripts/run_ardupilot_sim.sh` | ArduPilot launcher (auto GPU) |
| `camera_viewer.py` | Camera feed window |
| `drone_controller.py` | **Your landing algorithm** |
| `camera_viewer.py` | Drone camera window |
| `config.py` | Configuration |
## Sensors
## Sensors (GPS-Denied)
| Sensor | Data |
|--------|------|
| IMU | Orientation, angular velocity |
| Altimeter | Altitude, vertical velocity |
| Camera | 320x240 downward image |
| Camera | Downward image |
| Landing Pad | Relative position (when visible) |
## Options
```bash
--pattern, -p stationary, linear, circular, square, random
--speed, -s Speed in m/s (default: 0.5)
--pattern stationary, linear, circular, square, random
--speed Speed in m/s (default: 0.5)
```
## Documentation
## Docs
| Document | Description |
|----------|-------------|
| [Installation](docs/installation.md) | Setup guide |
| [Architecture](docs/architecture.md) | System overview |
| [ArduPilot](docs/ardupilot.md) | ArduPilot SITL |
| [Drone Guide](docs/drone_guide.md) | Algorithm guide |
- [Installation](docs/installation.md)
- [Architecture](docs/architecture.md)
- [ArduPilot](docs/ardupilot.md)
- [Gazebo](docs/gazebo.md)

View File

@@ -1,8 +1,8 @@
# Architecture Overview
## Operation Modes
## Modes
### 1. Standalone (Any Platform, 1 Terminal)
### 1. Standalone (1 Terminal)
```bash
python standalone_simulation.py --pattern circular
@@ -11,79 +11,68 @@ python standalone_simulation.py --pattern circular
```
┌────────────────────────────────────────┐
│ standalone_simulation.py │
│ PyBullet Physics + Camera + Controllers
│ PyBullet + Controllers + Camera
└────────────────────────────────────────┘
```
### 2. Gazebo + ROS 2 (2 Terminals)
**Terminal 1:**
```bash
ros2 launch gazebo/launch/drone_landing.launch.py
```
**Terminal 2:**
```bash
python run_gazebo.py --pattern circular
```
```
Terminal 1 Terminal 2
┌───────────────────┐ ┌───────────────────┐
│ Gazebo + Bridge │◄──────►│ run_gazebo.py │
│ (Physics) │ ROS │ + Controllers │
└───────────────────┘ └───────────────────┘
└───────────────────┘ ROS └───────────────────┘
```
### 3. ArduPilot SITL + Gazebo (2 Terminals)
**Terminal 1:**
```bash
gz sim -v4 -r ~/ardupilot_gazebo/worlds/iris_runway.sdf
```
**Terminal 2:**
```bash
sim_vehicle.py -v ArduCopter -f gazebo-iris --model JSON --console
```
### 3. ArduPilot GPS-Denied (2 Terminals)
```
Terminal 1 Terminal 2
┌───────────────────┐ ┌───────────────────┐
│ Gazebo + │◄──────►│ ArduPilot SITL │
│ ArduPilot Plugin │ JSON │ + MAVProxy │
└───────────────────┘ UDP └───────────────────┘
└───────────────────┘ └───────────────────┘
```
**Key features:**
- Full ArduPilot flight controller
- EKF, stabilization, failsafes
- MAVLink protocol
- Compatible with QGroundControl, Mission Planner
## Data Flow
## Key Components
### Standalone
```
Controller → PyBullet → Telemetry → Controller
```
| Component | Description |
|-----------|-------------|
| `standalone_simulation.py` | All-in-one PyBullet simulation |
| `run_gazebo.py` | Gazebo bridge + controllers |
### Gazebo
```
Controller → /cmd_vel → Gazebo → /odometry → Controller
```
### ArduPilot
```
Gazebo ◄─── JSON/UDP ───► SITL ◄─── MAVLink ───► MAVProxy
```
## Key Files
| File | Purpose |
|------|---------|
| `drone_controller.py` | Your landing algorithm |
| `camera_viewer.py` | Camera display window |
| `gazebo_bridge.py` | Gazebo ↔ ROS bridge |
| `camera_viewer.py` | Camera display |
| `config.py` | Configuration |
## ROS 2 Topics (Gazebo Mode)
| Topic | Direction | Description |
|-------|-----------|-------------|
| `/drone/telemetry` | ← | Sensor data (JSON) |
| `/cmd_vel` | → | Velocity commands |
| `/drone/camera` | ← | Camera images |
## Sensors
## GPS-Denied Sensors
| Sensor | Data |
|--------|------|
| IMU | orientation, angular_velocity |
| Altimeter | altitude, vertical_velocity |
| Velocity | x, y, z (m/s) |
| Camera | 320x240 image |
| Landing Pad | relative_x, relative_y (when visible) |
| IMU | Orientation, angular velocity |
| Altimeter | Altitude, vertical velocity |
| Camera | Downward image |
| Landing Pad | Relative position |
## Topics
| Topic | Direction |
|-------|-----------|
| `/cmd_vel` | → Drone commands |
| `/drone/telemetry` | ← Sensor data |
| `/drone/camera` | ← Camera images |

View File

@@ -1,17 +1,22 @@
# ArduPilot SITL Integration
# ArduPilot GPS-Denied Simulation
Run the simulation with a realistic ArduPilot flight controller.
Realistic flight controller simulation without GPS.
## Quick Start (2 Terminals)
**Terminal 1 - Gazebo:**
**Terminal 1:**
```bash
gz sim -v4 -r ~/ardupilot_gazebo/worlds/iris_runway.sdf
./scripts/run_ardupilot_sim.sh camera
```
**Terminal 2 - SITL + MAVProxy:**
**Terminal 2:**
```bash
sim_vehicle.py -v ArduCopter -f gazebo-iris --model JSON --console
# GPS-denied mode:
param set ARMING_CHECK 0
mode stabilize
arm throttle force
```
## Installation
@@ -21,82 +26,74 @@ sim_vehicle.py -v ArduCopter -f gazebo-iris --model JSON --console
source ~/.bashrc
```
This installs:
- ArduPilot SITL
- Gazebo Harmonic
- ardupilot_gazebo plugin
- MAVProxy
Installs: ArduPilot SITL, Gazebo, ardupilot_gazebo plugin, MAVProxy
## GPS-Denied Configuration
In MAVProxy console:
```bash
# Disable all pre-arm checks
param set ARMING_CHECK 0
# GPS-free flight modes
mode stabilize # Manual with stabilization
mode alt_hold # Altitude hold
mode guided_nogps # Guided without GPS
```
## GPU Support
The launcher auto-detects your GPU:
| GPU | Status |
|-----|--------|
| NVIDIA | Best performance |
| Intel integrated | Good for laptops |
| AMD | Good performance |
| Software | Works but slow |
## Camera Feed
### In Gazebo GUI
Click camera icon → Select drone camera
### Using camera_viewer
```bash
ros2 run ros_gz_bridge parameter_bridge /drone/camera@sensor_msgs/msg/Image[gz.msgs.Image
python camera_viewer.py --topic /drone/camera
```
## World Options
```bash
./scripts/run_ardupilot_sim.sh runway # Default
./scripts/run_ardupilot_sim.sh camera # With camera
```
## MAVProxy Commands
Once `sim_vehicle.py` is running:
```bash
# Set GUIDED mode
mode guided
# Arm
arm throttle
# Takeoff to 5m
takeoff 5
# Land
mode land
# Disarm
disarm
mode stabilize # Manual mode
mode guided_nogps # Autonomous (no GPS)
arm throttle force # Arm motors
takeoff 5 # Takeoff 5m
mode land # Land
```
## Available Worlds
```bash
# Iris on runway
gz sim -v4 -r ~/ardupilot_gazebo/worlds/iris_runway.sdf
# Zephyr plane
gz sim -v4 -r ~/ardupilot_gazebo/worlds/zephyr_runway.sdf
```
## Standalone SITL (No Gazebo)
```bash
sim_vehicle.py -v ArduCopter --console --map
```
This opens a 2D map view for testing without Gazebo.
## How It Works
```
Gazebo ArduPilot SITL
┌─────────────────┐ ┌─────────────────┐
│ iris_runway.sdf │◄────►│ sim_vehicle.py │
│ + ArduPilot │ JSON │ + MAVProxy │
│ Plugin │ UDP │ │
└─────────────────┘ └─────────────────┘
▼ MAVLink
Your Controller
```
The ArduPilot Gazebo plugin communicates with SITL via JSON over UDP.
## Troubleshooting
**sim_vehicle.py not found:**
### Simulation laggy
```bash
export PATH=$PATH:~/ardupilot/Tools/autotest
glxinfo | grep "OpenGL renderer"
# Should show GPU, not "llvmpipe"
```
**Plugin not loading:**
### Can't arm
```bash
export GZ_SIM_SYSTEM_PLUGIN_PATH=~/ardupilot_gazebo/build:$GZ_SIM_SYSTEM_PLUGIN_PATH
export GZ_SIM_RESOURCE_PATH=~/ardupilot_gazebo/models:~/ardupilot_gazebo/worlds:$GZ_SIM_RESOURCE_PATH
```
**Can't arm:**
```bash
# In MAVProxy, disable pre-arm checks
param set ARMING_CHECK 0
arm throttle force
```
### No camera
Use `./scripts/run_ardupilot_sim.sh camera` for camera world.

View File

@@ -1,6 +1,6 @@
# DroneController Guide
Implement your GPS-denied landing algorithm in `drone_controller.py`.
Implement your GPS-denied landing algorithm.
## Quick Start
@@ -9,25 +9,14 @@ Implement your GPS-denied landing algorithm in `drone_controller.py`.
3. Implement your algorithm
4. Test: `python standalone_simulation.py`
## Sensors Available
| Sensor | Description |
|--------|-------------|
| IMU | Orientation, angular velocity |
| Altimeter | Altitude, vertical velocity |
| Velocity | Estimated velocity (x, y, z) |
| Camera | 320x240 downward image |
| Landing Pad | Relative position (may be null!) |
## Function to Implement
```python
def calculate_landing_maneuver(self, telemetry, rover_telemetry):
# Your code here
return (thrust, pitch, roll, yaw)
```
## Sensor Data
## Sensors (GPS-Denied)
```python
# Altitude
@@ -58,23 +47,23 @@ if landing_pad:
```python
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)
alt = telemetry.get('altimeter', {})
altitude = alt.get('altitude', 5.0)
vert_vel = alt.get('vertical_velocity', 0.0)
velocity = telemetry.get('velocity', {})
vel_x = velocity.get('x', 0.0)
vel_y = velocity.get('y', 0.0)
vel = telemetry.get('velocity', {})
vel_x = vel.get('x', 0.0)
vel_y = vel.get('y', 0.0)
landing_pad = telemetry.get('landing_pad')
pad = telemetry.get('landing_pad')
# Altitude control
thrust = 0.5 * (0 - altitude) - 0.3 * vertical_vel
# Altitude PD control
thrust = 0.5 * (0 - altitude) - 0.3 * vert_vel
# Horizontal control
if landing_pad:
pitch = 0.3 * landing_pad['relative_x'] - 0.2 * vel_x
roll = 0.3 * landing_pad['relative_y'] - 0.2 * vel_y
if pad:
pitch = 0.3 * pad['relative_x'] - 0.2 * vel_x
roll = 0.3 * pad['relative_y'] - 0.2 * vel_y
else:
pitch = -0.2 * vel_x
roll = -0.2 * vel_y
@@ -82,33 +71,16 @@ def calculate_landing_maneuver(self, telemetry, rover_telemetry):
return (thrust, pitch, roll, 0.0)
```
## Using the Camera
```python
import cv2
import numpy as np
import base64
camera = telemetry.get('camera', {})
image_b64 = camera.get('image')
if image_b64:
image_bytes = base64.b64decode(image_b64)
nparr = np.frombuffer(image_bytes, np.uint8)
image = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
# Process image...
```
## Testing
```bash
# Easy - stationary
# Easy
python standalone_simulation.py --pattern stationary
# Medium - circular
# Medium
python standalone_simulation.py --pattern circular --speed 0.3
# Hard - random
# Hard
python standalone_simulation.py --pattern random --speed 0.5
```
@@ -118,9 +90,9 @@ Edit `config.py`:
```python
CONTROLLER = {
"Kp_z": 0.5, # Altitude proportional
"Kd_z": 0.3, # Altitude derivative
"Kp_xy": 0.3, # Horizontal proportional
"Kd_xy": 0.2, # Horizontal derivative
"Kp_z": 0.5,
"Kd_z": 0.3,
"Kp_xy": 0.3,
"Kd_xy": 0.2,
}
```

View File

@@ -2,43 +2,38 @@
## Quick Start (2 Terminals)
**Terminal 1 - Gazebo:**
**Terminal 1:**
```bash
ros2 launch gazebo/launch/drone_landing.launch.py
```
**Terminal 2 - Controllers:**
**Terminal 2:**
```bash
source activate.sh
python run_gazebo.py --pattern circular
```
## Command Options
```bash
python run_gazebo.py --pattern circular --speed 0.5
Options:
--pattern, -p stationary, linear, circular, square, random
--speed, -s Rover speed in m/s (default: 0.5)
--amplitude, -a Movement radius (default: 2.0)
--no-rover Disable rover controller
```
## View Camera
## Camera Feed
```bash
python camera_viewer.py --topic /drone/camera
```
## Options
```bash
--pattern stationary, linear, circular, square, random
--speed Rover speed in m/s (default: 0.5)
--no-rover Disable rover movement
```
## Sensors
| Sensor | Description |
|--------|-------------|
| IMU | Orientation, angular velocity |
| Altimeter | Altitude, vertical velocity |
| Velocity | Estimated velocity (x, y, z) |
| Camera | Downward-facing image |
| Sensor | Source |
|--------|--------|
| IMU | Gazebo odometry |
| Altimeter | Z position |
| Camera | Camera sensor |
| Landing Pad | Relative position |
## ROS 2 Topics
@@ -47,24 +42,23 @@ python camera_viewer.py --topic /drone/camera
|-------|-----------|
| `/cmd_vel` | Your commands → Drone |
| `/drone/telemetry` | Sensors → You |
| `/drone/camera` | Camera → You |
| `/rover/telemetry` | Rover position |
| `/drone/camera` | Camera images |
## Headless Mode (WSL2)
```bash
# Server only (no GUI)
ign gazebo -s gazebo/worlds/drone_landing.sdf
```
## Troubleshooting
**Drone falls:**
- Check `run_gazebo.py` is running
- Check topic: `ros2 topic echo /drone/cmd_vel`
Check `run_gazebo.py` is running
**Rover doesn't move:**
- Check topic: `ros2 topic echo /rover/cmd_vel`
**No camera:**
```bash
python camera_viewer.py --list # Find topics
```
**Model not found:**
```bash

View File

@@ -3,21 +3,17 @@
## Quick Install
```bash
# Ubuntu/Debian
./setup/install_ubuntu.sh
source activate.sh
# Test
python standalone_simulation.py
```
## Install Scripts
## Scripts
| Platform | Command |
|----------|---------|
| Ubuntu/Debian | `./setup/install_ubuntu.sh` |
| ArduPilot SITL | `./setup/install_ardupilot.sh` |
| Arch Linux | `./setup/install_arch.sh` |
| macOS | `./setup/install_macos.sh` |
| Windows | `.\setup\install_windows.ps1` |
@@ -26,8 +22,8 @@ python standalone_simulation.py
| Mode | Ubuntu | macOS | Windows |
|------|--------|-------|---------|
| Standalone | ✅ | ✅ | ✅ |
| Gazebo + ROS 2 | ✅ | ❌ | WSL2 |
| ArduPilot SITL | ✅ | ❌ | WSL2 |
| Gazebo | ✅ | ❌ | WSL2 |
| ArduPilot | ✅ | ❌ | WSL2 |
---
@@ -36,74 +32,46 @@ python standalone_simulation.py
```bash
./setup/install_ubuntu.sh
source activate.sh
python standalone_simulation.py
```
**Installs:**
- ROS 2 Humble/Jazzy
- Gazebo
- Python packages (pybullet, numpy, opencv, pymavlink)
Installs: ROS 2, Gazebo, PyBullet, OpenCV, pymavlink
---
## ArduPilot SITL
For realistic flight controller simulation:
```bash
./setup/install_ardupilot.sh
source ~/.bashrc
```
**Installs:**
- Micro-XRCE-DDS-Gen (required for DDS)
- ArduPilot SITL
- ardupilot_gz (Gazebo integration)
- MAVProxy (`~/.local/bin/mavproxy.py`)
Installs: ArduPilot SITL, ardupilot_gazebo, MAVProxy
**Run (2 terminals):**
Terminal 1:
**Run:**
```bash
source ~/ardu_ws/install/setup.bash
ros2 launch ardupilot_gz_bringup iris_runway.launch.py
```
Terminal 2:
```bash
mavproxy.py --console --map --master=:14550
./scripts/run_ardupilot_sim.sh camera
```
---
## Windows (WSL2)
## GPU Support
1. Install WSL2:
```powershell
wsl --install -d Ubuntu-22.04
```
The simulation auto-detects GPU:
2. Open Ubuntu and run:
| Priority | GPU Type | Notes |
|----------|----------|-------|
| 1 | NVIDIA | Best performance |
| 2 | Intel integrated | Good for laptops |
| 3 | AMD | Good performance |
| 4 | Software (llvmpipe) | Slow fallback |
Check your GPU:
```bash
./setup/install_ubuntu.sh
source activate.sh
python standalone_simulation.py
glxinfo | grep "OpenGL renderer"
```
---
## macOS
```bash
./setup/install_macos.sh
source activate.sh
python standalone_simulation.py
```
**Note:** ROS 2 and Gazebo not supported. Use standalone mode.
---
## Manual Install
```bash
@@ -115,49 +83,28 @@ python standalone_simulation.py
---
## Verification
## Troubleshooting
### Simulation is laggy
```bash
python -c "import pybullet; print('PyBullet OK')"
python -c "import cv2; print('OpenCV OK')"
python -c "from pymavlink import mavutil; print('pymavlink OK')"
# Check GPU (should NOT show "llvmpipe")
glxinfo | grep "OpenGL renderer"
# Install GPU drivers
sudo apt install mesa-utils # Intel/AMD
sudo apt install nvidia-driver-535 # NVIDIA
```
---
## Troubleshooting
### MAVProxy not found
```bash
# Install
pip3 install --user mavproxy
# Add to PATH
echo 'export PATH=$PATH:~/.local/bin' >> ~/.bashrc
source ~/.bashrc
# Verify
which mavproxy.py
export PATH=$PATH:~/.local/bin
```
### microxrceddsgen not found
### sim_vehicle.py not found
```bash
# Install (needed for ArduPilot DDS)
git clone --recurse-submodules https://github.com/eProsima/Micro-XRCE-DDS-Gen.git ~/Micro-XRCE-DDS-Gen
cd ~/Micro-XRCE-DDS-Gen
./gradlew assemble
# Add to PATH
echo 'export PATH=$PATH:~/Micro-XRCE-DDS-Gen/scripts' >> ~/.bashrc
source ~/.bashrc
```
### Build errors
```bash
# Rebuild with override flag
cd ~/ardu_ws
colcon build --packages-up-to ardupilot_gz_bringup --allow-overriding ros_gz_bridge ros_gz_sim sdformat_urdf
export PATH=$PATH:~/ardupilot/Tools/autotest
```

View File

@@ -0,0 +1,225 @@
<?xml version="1.0" ?>
<!--
ArduPilot Iris Drone with Camera - GPS-Denied Simulation
This world includes:
- Iris quadcopter with downward camera
- ArduPilot plugin for SITL
- Landing pad for targeting
Usage:
gz sim -v4 -r iris_camera.sdf
sim_vehicle.py -v ArduCopter -f gazebo-iris --model JSON --console
-->
<sdf version="1.9">
<world name="iris_camera_world">
<!-- Physics optimized for real-time -->
<physics name="1ms" type="ode">
<max_step_size>0.001</max_step_size>
<real_time_factor>1.0</real_time_factor>
<real_time_update_rate>1000</real_time_update_rate>
</physics>
<!-- GPU rendering plugins -->
<plugin filename="gz-sim-physics-system" name="gz::sim::systems::Physics"/>
<plugin filename="gz-sim-sensors-system" name="gz::sim::systems::Sensors">
<render_engine>ogre2</render_engine>
</plugin>
<plugin filename="gz-sim-user-commands-system" name="gz::sim::systems::UserCommands"/>
<plugin filename="gz-sim-scene-broadcaster-system" name="gz::sim::systems::SceneBroadcaster"/>
<!-- Lighting -->
<light type="directional" name="sun">
<cast_shadows>true</cast_shadows>
<pose>0 0 10 0 0 0</pose>
<diffuse>0.8 0.8 0.8 1</diffuse>
<specular>0.2 0.2 0.2 1</specular>
<attenuation>
<range>1000</range>
<constant>0.9</constant>
<linear>0.01</linear>
<quadratic>0.001</quadratic>
</attenuation>
<direction>-0.5 0.1 -0.9</direction>
</light>
<!-- Sky -->
<scene>
<ambient>0.4 0.4 0.4 1</ambient>
<background>0.7 0.7 0.9 1</background>
<shadows>true</shadows>
</scene>
<!-- Ground plane with texture -->
<model name="ground_plane">
<static>true</static>
<link name="link">
<collision name="collision">
<geometry>
<plane>
<normal>0 0 1</normal>
<size>100 100</size>
</plane>
</geometry>
</collision>
<visual name="visual">
<geometry>
<plane>
<normal>0 0 1</normal>
<size>100 100</size>
</plane>
</geometry>
<material>
<ambient>0.3 0.3 0.3 1</ambient>
<diffuse>0.5 0.5 0.5 1</diffuse>
</material>
</visual>
</link>
</model>
<!-- Landing Pad (Green with H marker) -->
<model name="landing_pad">
<static>false</static>
<pose>0 0 0.02 0 0 0</pose>
<link name="pad_link">
<inertial>
<mass>50</mass>
</inertial>
<collision name="collision">
<geometry>
<box>
<size>1.5 1.5 0.04</size>
</box>
</geometry>
</collision>
<visual name="visual">
<geometry>
<box>
<size>1.5 1.5 0.04</size>
</box>
</geometry>
<material>
<ambient>0.1 0.6 0.1 1</ambient>
<diffuse>0.2 0.8 0.2 1</diffuse>
</material>
</visual>
<!-- H marker -->
<visual name="h_marker">
<pose>0 0 0.025 0 0 0</pose>
<geometry>
<box>
<size>0.1 0.6 0.01</size>
</box>
</geometry>
<material>
<ambient>1 1 1 1</ambient>
<diffuse>1 1 1 1</diffuse>
</material>
</visual>
<visual name="h_marker_cross">
<pose>0 0 0.025 0 0 1.5708</pose>
<geometry>
<box>
<size>0.1 0.3 0.01</size>
</box>
</geometry>
<material>
<ambient>1 1 1 1</ambient>
<diffuse>1 1 1 1</diffuse>
</material>
</visual>
</link>
<!-- Velocity control for moving pad -->
<plugin filename="gz-sim-velocity-control-system"
name="gz::sim::systems::VelocityControl">
<topic>/landing_pad/cmd_vel</topic>
</plugin>
</model>
<!-- Iris Drone with Camera -->
<include>
<uri>model://iris_with_ardupilot</uri>
<name>iris</name>
<pose>0 0 0.195 0 0 0</pose>
</include>
<!-- If iris model doesn't exist, create simple drone -->
<model name="camera_drone">
<pose>0 2 0.5 0 0 0</pose>
<link name="base_link">
<inertial>
<mass>1.5</mass>
<inertia>
<ixx>0.029</ixx>
<iyy>0.029</iyy>
<izz>0.055</izz>
</inertia>
</inertial>
<collision name="collision">
<geometry>
<box>
<size>0.4 0.4 0.1</size>
</box>
</geometry>
</collision>
<visual name="body">
<geometry>
<box>
<size>0.4 0.4 0.1</size>
</box>
</geometry>
<material>
<ambient>0.2 0.2 0.2 1</ambient>
<diffuse>0.3 0.3 0.3 1</diffuse>
</material>
</visual>
<!-- Downward Camera -->
<sensor name="camera" type="camera">
<pose>0 0 -0.05 0 1.5708 0</pose>
<always_on>true</always_on>
<update_rate>30</update_rate>
<camera>
<horizontal_fov>1.047</horizontal_fov>
<image>
<width>640</width>
<height>480</height>
<format>R8G8B8</format>
</image>
<clip>
<near>0.1</near>
<far>100</far>
</clip>
</camera>
<topic>/drone/camera</topic>
</sensor>
<!-- IMU -->
<sensor name="imu" type="imu">
<always_on>true</always_on>
<update_rate>250</update_rate>
<topic>/drone/imu</topic>
</sensor>
</link>
<!-- Velocity control -->
<plugin filename="gz-sim-velocity-control-system"
name="gz::sim::systems::VelocityControl">
<topic>/drone/cmd_vel</topic>
</plugin>
<!-- Odometry -->
<plugin filename="gz-sim-odometry-publisher-system"
name="gz::sim::systems::OdometryPublisher">
<odom_topic>/drone/odometry</odom_topic>
<odom_frame>world</odom_frame>
<robot_base_frame>camera_drone</robot_base_frame>
</plugin>
</model>
</world>
</sdf>

163
scripts/run_ardupilot_sim.sh Executable file
View File

@@ -0,0 +1,163 @@
#!/bin/bash
# =============================================================================
# ArduPilot GPS-Denied Simulation Launcher
# =============================================================================
# Launches Gazebo with GPU acceleration and camera support
# Automatically detects GPU: NVIDIA > Intel/AMD integrated > Software
#
# Usage:
# ./scripts/run_ardupilot_sim.sh # Default iris_runway
# ./scripts/run_ardupilot_sim.sh camera # With camera world
# =============================================================================
set -e
echo "=============================================="
echo " ArduPilot GPS-Denied Simulation"
echo "=============================================="
# =============================================================================
# GPU DETECTION & CONFIGURATION
# =============================================================================
echo ""
echo "[INFO] Detecting GPU..."
# Disable software rendering by default
export LIBGL_ALWAYS_SOFTWARE=0
# Check for NVIDIA dedicated GPU
if command -v nvidia-smi &> /dev/null && nvidia-smi &> /dev/null; then
GPU_NAME=$(nvidia-smi --query-gpu=name --format=csv,noheader 2>/dev/null | head -1)
echo "[GPU] NVIDIA (dedicated): $GPU_NAME"
export __GLX_VENDOR_LIBRARY_NAME=nvidia
export __NV_PRIME_RENDER_OFFLOAD=1
export __VK_LAYER_NV_optimus=NVIDIA_only
GPU_TYPE="nvidia"
# Check for Intel integrated GPU
elif [ -d "/sys/class/drm/card0" ] && grep -qi "intel" /sys/class/drm/card0/device/vendor 2>/dev/null; then
echo "[GPU] Intel (integrated)"
export MESA_GL_VERSION_OVERRIDE=3.3
export LIBVA_DRIVER_NAME=iHD # Intel media driver
GPU_TYPE="intel"
# Check via glxinfo
elif command -v glxinfo &> /dev/null; then
GPU_NAME=$(glxinfo 2>/dev/null | grep "OpenGL renderer" | cut -d: -f2 | xargs)
if [[ "$GPU_NAME" == *"NVIDIA"* ]]; then
echo "[GPU] NVIDIA: $GPU_NAME"
export __GLX_VENDOR_LIBRARY_NAME=nvidia
GPU_TYPE="nvidia"
elif [[ "$GPU_NAME" == *"Intel"* ]]; then
echo "[GPU] Intel: $GPU_NAME"
export MESA_GL_VERSION_OVERRIDE=3.3
GPU_TYPE="intel"
elif [[ "$GPU_NAME" == *"AMD"* ]] || [[ "$GPU_NAME" == *"Radeon"* ]]; then
echo "[GPU] AMD: $GPU_NAME"
export MESA_GL_VERSION_OVERRIDE=3.3
GPU_TYPE="amd"
elif [[ "$GPU_NAME" == *"llvmpipe"* ]] || [[ "$GPU_NAME" == *"software"* ]]; then
echo "[GPU] Software rendering (llvmpipe) - SLOW!"
echo "[WARN] Install GPU drivers for better performance"
GPU_TYPE="software"
else
echo "[GPU] $GPU_NAME"
export MESA_GL_VERSION_OVERRIDE=3.3
GPU_TYPE="other"
fi
# Fallback to Mesa defaults
else
echo "[GPU] Unknown - using Mesa defaults"
export MESA_GL_VERSION_OVERRIDE=3.3
GPU_TYPE="unknown"
fi
# For integrated graphics, ensure Mesa works well
if [[ "$GPU_TYPE" == "intel" ]] || [[ "$GPU_TYPE" == "amd" ]] || [[ "$GPU_TYPE" == "other" ]]; then
export MESA_LOADER_DRIVER_OVERRIDE=""
export DRI_PRIME=0 # Use primary GPU (integrated)
fi
echo "[INFO] GPU type: $GPU_TYPE"
# =============================================================================
# GAZEBO PATHS
# =============================================================================
export GZ_SIM_SYSTEM_PLUGIN_PATH="${HOME}/ardupilot_gazebo/build:${GZ_SIM_SYSTEM_PLUGIN_PATH}"
export GZ_SIM_RESOURCE_PATH="${HOME}/ardupilot_gazebo/models:${HOME}/ardupilot_gazebo/worlds:${GZ_SIM_RESOURCE_PATH}"
# Add local models
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
export GZ_SIM_RESOURCE_PATH="${PROJECT_DIR}/gazebo/models:${GZ_SIM_RESOURCE_PATH}"
# =============================================================================
# CHECK INSTALLATION
# =============================================================================
if [ ! -d "${HOME}/ardupilot_gazebo" ]; then
echo "[ERROR] ardupilot_gazebo not found!"
echo "Run: ./setup/install_ardupilot.sh"
exit 1
fi
if [ ! -f "${HOME}/ardupilot_gazebo/build/libArduPilotPlugin.so" ]; then
echo "[ERROR] ArduPilot plugin not built!"
echo "Run: cd ~/ardupilot_gazebo && mkdir -p build && cd build && cmake .. && make -j4"
exit 1
fi
# =============================================================================
# SELECT WORLD
# =============================================================================
WORLD_ARG="${1:-runway}"
case "$WORLD_ARG" in
camera)
WORLD="${PROJECT_DIR}/gazebo/worlds/iris_camera.sdf"
echo "[INFO] Using camera world (with downward camera)"
;;
runway)
WORLD="${HOME}/ardupilot_gazebo/worlds/iris_runway.sdf"
;;
*)
WORLD="$WORLD_ARG"
;;
esac
if [ ! -f "$WORLD" ]; then
echo "[ERROR] World file not found: $WORLD"
echo "Available worlds:"
ls -1 ~/ardupilot_gazebo/worlds/*.sdf 2>/dev/null || echo " None in ardupilot_gazebo"
ls -1 "${PROJECT_DIR}/gazebo/worlds/"*.sdf 2>/dev/null || echo " None in local"
exit 1
fi
# =============================================================================
# INSTRUCTIONS
# =============================================================================
echo ""
echo "=============================================="
echo " Starting Gazebo"
echo "=============================================="
echo ""
echo "World: $WORLD"
echo ""
echo "After Gazebo starts, in another terminal run:"
echo ""
echo " sim_vehicle.py -v ArduCopter -f gazebo-iris --model JSON --console"
echo ""
echo "For GPS-DENIED mode, in MAVProxy console:"
echo ""
echo " param set ARMING_CHECK 0"
echo " mode stabilize"
echo " arm throttle force"
echo ""
echo "=============================================="
echo ""
# =============================================================================
# RUN GAZEBO
# =============================================================================
gz sim -v4 -r "$WORLD"