From 5c0d3e2fb44e4f08c52b1d83ef4bea29dcfd6453 Mon Sep 17 00:00:00 2001 From: default Date: Mon, 9 Feb 2026 04:20:22 +0000 Subject: [PATCH] Update Install Scripts --- README.md | 300 +++++-------- models/iris_with_ardupilot/model.config | 13 + models/iris_with_ardupilot/model.sdf | 311 +++++++++++++ models/iris_with_camera/model.sdf | 166 ++++--- scripts/run_simulation.sh | 244 +++++++---- scripts/setup_gazebo_nvidia.sh | 25 -- scripts/setup_wsl.sh | 174 -------- setup.sh | 552 ++++++++++++------------ worlds/empty_custom.world | 17 + worlds/iris_runway.world | 106 +++++ 10 files changed, 1072 insertions(+), 836 deletions(-) create mode 100644 models/iris_with_ardupilot/model.config create mode 100644 models/iris_with_ardupilot/model.sdf delete mode 100755 scripts/setup_gazebo_nvidia.sh delete mode 100755 scripts/setup_wsl.sh create mode 100644 worlds/iris_runway.world diff --git a/README.md b/README.md index da85877..0bdcb7e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # UAV-UGV Gazebo SITL Simulation ## GPS-Denied Navigation with Geofencing -A complete simulation environment for UAV (drone) and UGV (ground vehicle) development using **GPS-denied navigation** with vision-based localization, while maintaining GPS-based geofencing for safety. +A production-ready simulation environment for UAV (drone) and UGV (ground vehicle) development using **GPS-denied navigation** with vision-based localization, while maintaining GPS-based geofencing for safety. ## Key Feature: GPS-Denied Navigation @@ -14,15 +14,78 @@ A complete simulation environment for UAV (drone) and UGV (ground vehicle) devel **GPS Usage**: GPS is ONLY used for: - Geofencing (safety boundaries) -- Initial position reference (optional) - NOT used for waypoint navigation - NOT used for position control -This simulates real-world GPS-denied environments like: -- Indoor spaces -- Urban canyons -- GPS-jammed areas -- Under bridges/tunnels +## System Requirements + +- **Ubuntu 22.04 LTS** (or 24.04) +- **16GB RAM** recommended (8GB minimum) +- **50GB disk space** (for ArduPilot + Gazebo) +- NVIDIA GPU recommended but not required + +### Supported Platforms +- Native Ubuntu Linux +- Windows WSL2 with Ubuntu 22.04 + +## Installation (One Command) + +```bash +# Clone the repository +git clone https://git.sirblob.co/SirBlob/simulation.git +cd simulation + +# Run the complete setup (installs everything) +bash setup.sh +``` + +The setup script installs: +- ROS 2 Humble +- Gazebo 11 +- ArduPilot SITL +- ardupilot_gazebo plugin +- MAVROS +- Python dependencies + +**Note**: Full installation takes 20-40 minutes depending on your internet speed. + +## Quick Start + +```bash +# Navigate to project +cd ~/simulation # or wherever you cloned it + +# Activate environment (sets up ROS 2, Gazebo, ArduPilot, Python) +source activate_venv.sh + +# Run simulation +bash scripts/run_simulation.sh + +# For WSL (if graphics issues): +bash scripts/run_simulation.sh --software-render +``` + +## Controlling the UAV + +Once the simulation is running, control via ROS 2: + +```bash +# Arm the drone +ros2 service call /mavros/cmd/arming mavros_msgs/srv/CommandBool "{value: true}" + +# Set GUIDED mode (allows position control) +ros2 service call /mavros/set_mode mavros_msgs/srv/SetMode "{custom_mode: 'GUIDED'}" + +# Takeoff to 5 meters +ros2 service call /mavros/cmd/takeoff mavros_msgs/srv/CommandTOL "{altitude: 5}" + +# Fly to position (LOCAL coordinates - no GPS!) +ros2 topic pub /mavros/setpoint_position/local geometry_msgs/PoseStamped \ + "{header: {frame_id: 'map'}, pose: {position: {x: 10, y: 5, z: 5}}}" + +# Land +ros2 service call /mavros/cmd/land mavros_msgs/srv/CommandTOL "{}" +``` ## Features @@ -30,73 +93,10 @@ This simulates real-world GPS-denied environments like: - **Ground vehicle (UGV)** with vision sensors - **Visual odometry** - camera-based position estimation - **Optical flow** - velocity estimation from downward camera -- **Landmark navigation** - visual feature tracking - **GPS geofencing** - safety boundaries only -- **Single command launch** - everything runs from one script -- **NVIDIA GPU acceleration** support -- **Python virtual environment** for isolated dependencies -- **GPS-denied worlds** - indoor and urban environments - -## System Requirements - -- **Ubuntu 22.04 LTS** (or 24.04 with ROS 2 Jazzy) -- **Python 3.10+** -- **ROS 2 Humble** (or Jazzy for Ubuntu 24.04) -- 8GB RAM minimum (16GB recommended) -- NVIDIA GPU recommended - -### WSL2 Support (Windows) - -This project supports **Windows Subsystem for Linux (WSL2)**: -- Windows 10 (21H2+) or Windows 11 -- WSL2 with Ubuntu 22.04 -- GUI support via WSLg (Windows 11) or VcXsrv (Windows 10) -- See [WSL Setup Guide](docs/wsl_setup_guide.md) for detailed instructions - -## Quick Start - -### Linux (Native) - -```bash -# 1. Clone repository -cd ~/ros2_ws/src -git clone https://git.sirblob.co/SirBlob/simulation.git uav_ugv_simulation -cd uav_ugv_simulation - -# 2. Run setup (installs everything) -bash setup.sh - -# 3. Restart terminal or reload bash -source ~/.bashrc - -# 4. Activate virtual environment and run -source activate_venv.sh -bash scripts/run_simulation.sh -``` - -### WSL2 (Windows) - -```bash -# 1. Clone repository -cd ~ -git clone https://git.sirblob.co/SirBlob/simulation.git uav_ugv_simulation -cd uav_ugv_simulation - -# 2. Run WSL-specific setup -bash scripts/setup_wsl.sh - -# 3. Restart terminal -exit -# Reopen WSL terminal - -# 4. Run simulation -cd ~/uav_ugv_simulation -source activate_venv.sh -bash scripts/run_simulation.sh - -# If graphics are slow, use software rendering: -bash scripts/run_simulation.sh --software-render -``` +- **ArduPilot SITL** - real flight controller firmware +- **MAVROS** - ROS 2 interface for MAVLink +- **Multiple worlds** - indoor warehouse, urban canyon ## GPS-Denied Navigation Architecture @@ -121,103 +121,57 @@ bash scripts/run_simulation.sh --software-render │ ▼ ┌─────────────────────────────────────────────────────┐ -│ Navigation Controller │ -│ Commands: "Move 5m forward, 3m right" │ -│ (Relative coordinates only, NO GPS waypoints) │ +│ ArduPilot Flight Controller │ +│ Receives position via MAVROS (external nav) │ +│ Controls motors based on local setpoints │ └─────────────────────────────────────────────────────┘ - - SEPARATE SAFETY LAYER (GPS-based): -┌─────────────────────────────────────────────────────┐ -│ Geofence Monitor │ -│ GPS position → Check against boundaries │ -│ If outside: Emergency RTL or hold │ -└─────────────────────────────────────────────────────┘ -``` - -## Navigation Modes - -### 1. **Vision-Only Mode** (Default) -- Uses camera for all position estimates -- Suitable for structured environments -- Requires good lighting and visual features - -### 2. **Optical Flow Mode** -- Uses downward camera for velocity -- Works well at low altitudes -- Good for hovering and slow flight - -### 3. **Hybrid Mode** -- Combines visual odometry + optical flow + IMU -- Most robust approach -- Recommended for complex missions - -## Geofencing Configuration - -Edit `config/geofence_params.yaml`: - -```yaml -geofence: - enabled: true - use_gps: true # GPS ONLY for geofence - - # Define boundaries (GPS coordinates) - fence_type: "polygon" # or "circle" - - # Polygon fence (lat/lon points) - polygon_points: - - {lat: 47.397742, lon: 8.545594} # Point 1 - - {lat: 47.398242, lon: 8.545594} # Point 2 - - {lat: 47.398242, lon: 8.546094} # Point 3 - - {lat: 47.397742, lon: 8.546094} # Point 4 - - # Or circle fence - center_lat: 47.397742 - center_lon: 8.545594 - radius_meters: 100 - - # Actions on breach - action: "RTL" # Return to launch - max_altitude: 50 # meters -``` - -## Example Mission (Relative Coordinates) - -```python -# Example: Navigate to visual landmark - -# Define mission in RELATIVE coordinates -mission_waypoints = [ - {"x": 0, "y": 0, "z": 5}, # Takeoff to 5m - {"x": 10, "y": 0, "z": 5}, # Move 10m forward - {"x": 10, "y": 5, "z": 5}, # Move 5m right - {"x": 0, "y": 5, "z": 5}, # Return to start (offset) - {"x": 0, "y": 0, "z": 5}, # Back to takeoff point - {"x": 0, "y": 0, "z": 0}, # Land -] - -# GPS is NEVER used for these waypoints -# Position estimated from visual odometry ``` ## Project Structure -- `launch/` - ROS 2 launch files -- `worlds/` - Gazebo world files (indoor, urban) -- `models/` - Robot models (Iris with cameras, UGV) -- `src/vision/` - Visual odometry, optical flow -- `src/localization/` - Position estimation, sensor fusion -- `src/navigation/` - Path planning (relative coordinates) -- `src/safety/` - Geofencing (GPS-based) -- `config/` - Configuration files +``` +simulation/ +├── setup.sh # One-command installation +├── activate_venv.sh # Environment activation +├── scripts/ +│ ├── run_simulation.sh # Launch full simulation +│ └── kill_simulation.sh # Stop all processes +├── worlds/ # Gazebo world files +├── models/ # UAV and UGV models +├── src/ +│ ├── vision/ # Visual odometry, optical flow +│ ├── localization/ # EKF sensor fusion +│ ├── navigation/ # Path planning +│ ├── control/ # UAV/UGV controllers +│ └── safety/ # Geofencing +├── config/ # Configuration files +└── docs/ # Documentation +``` ## Documentation -- [Setup Guide](docs/setup_guide.md) - Linux installation -- [WSL Setup Guide](docs/wsl_setup_guide.md) - Windows WSL2 installation -- [Usage Guide](docs/usage.md) -- [Architecture Overview](docs/architecture.md) -- [GPS-Denied Navigation](docs/gps_denied_navigation.md) -- [Troubleshooting](docs/troubleshooting.md) +- [Setup Guide](docs/setup_guide.md) - Detailed installation +- [WSL Setup Guide](docs/wsl_setup_guide.md) - Windows WSL2 +- [Usage Guide](docs/usage.md) - How to use +- [Architecture](docs/architecture.md) - System design +- [GPS-Denied Navigation](docs/gps_denied_navigation.md) - Navigation approach +- [Troubleshooting](docs/troubleshooting.md) - Common issues + +## Simulation Options + +```bash +# Default (ArduPilot Iris world) +bash scripts/run_simulation.sh + +# Custom world +bash scripts/run_simulation.sh --world worlds/indoor_warehouse.world + +# Rover instead of copter +bash scripts/run_simulation.sh --vehicle rover + +# Software rendering (WSL/no GPU) +bash scripts/run_simulation.sh --software-render +``` ## Key Differences from GPS Navigation @@ -229,25 +183,3 @@ mission_waypoints = [ | Indoor Capability | No | Yes | | Drift | Minimal | Accumulates over time | | Geofencing | GPS-based | GPS-based (safety only) | -| Use Cases | Outdoor, open sky | Indoor, urban, GPS-jammed | - -## Running Different Scenarios - -```bash -# Indoor warehouse (no GPS available) -bash scripts/run_simulation.sh --world worlds/indoor_warehouse.world - -# Urban canyon (degraded GPS) -bash scripts/run_simulation.sh --world worlds/urban_canyon.world - -# Open outdoor (GPS available but not used for nav) -bash scripts/run_simulation.sh --world worlds/empty_custom.world -``` - -## License - -MIT License - -## Contributing - -Contributions welcome! Please ensure all navigation remains GPS-denied (except geofencing). diff --git a/models/iris_with_ardupilot/model.config b/models/iris_with_ardupilot/model.config new file mode 100644 index 0000000..899e26b --- /dev/null +++ b/models/iris_with_ardupilot/model.config @@ -0,0 +1,13 @@ + + + Iris with ArduPilot + 1.0 + model.sdf + + UAV-UGV Simulation + + + Iris quadcopter with ArduPilot SITL plugin for GPS-denied navigation testing. + Includes forward and downward cameras for visual odometry. + + diff --git a/models/iris_with_ardupilot/model.sdf b/models/iris_with_ardupilot/model.sdf new file mode 100644 index 0000000..cf49256 --- /dev/null +++ b/models/iris_with_ardupilot/model.sdf @@ -0,0 +1,311 @@ + + + + 0 0 0.194923 0 0 0 + + + + 0 0 0 0 0 0 + 1.5 + + 0.029125 + 0 + 0 + 0.029125 + 0 + 0.055225 + + + + + 0 0 -0.08 0 0 0 + + 0.47 0.47 0.11 + + + + + 0 0 0 0 0 0 + + + model://iris/meshes/iris.dae + 1 1 1 + + + + + + + 0 0 0 0 0 0 + + 0.3 0.3 0.1 + + + 0.2 0.2 0.8 1 + 0.2 0.2 0.8 1 + + + + + + true + 200 + + + 00.0003 + 00.0003 + 00.0003 + + + 00.017 + 00.017 + 00.017 + + + + + + + + 0.13 -0.22 0.023 0 0 0 + + 0.025 + + 9.75e-0600 + 0.00016670400.000167604 + + + + 0.10.01 + 0.1 0.1 0.1 1 + + + + base_link + rotor_0 + + 0 0 1 + -1e161e16 + + + + + + -0.13 0.22 0.023 0 0 0 + + 0.025 + + 9.75e-0600 + 0.00016670400.000167604 + + + + 0.10.01 + 0.1 0.1 0.1 1 + + + + base_link + rotor_1 + + 0 0 1 + -1e161e16 + + + + + + 0.13 0.22 0.023 0 0 0 + + 0.025 + + 9.75e-0600 + 0.00016670400.000167604 + + + + 0.10.01 + 0.1 0.1 0.1 1 + + + + base_link + rotor_2 + + 0 0 1 + -1e161e16 + + + + + + -0.13 -0.22 0.023 0 0 0 + + 0.025 + + 9.75e-0600 + 0.00016670400.000167604 + + + + 0.10.01 + 0.1 0.1 0.1 1 + + + + base_link + rotor_3 + + 0 0 1 + -1e161e16 + + + + + + 0.1 0 0 0 0 0 + + 0.01 + + 1e-500 + 1e-501e-5 + + + + 0.02 0.02 0.02 + 0 0 0 1 + + + + 1.57 + + 640 + 480 + R8G8B8 + + 0.1100 + + 1 + 30 + true + + + /uav + image_raw:=camera/forward/image_raw + camera_info:=camera/forward/camera_info + + forward_camera + forward_camera_link + + + + + base_link + forward_camera_link + + + + + 0 0 -0.05 0 1.5708 0 + + 0.01 + + 1e-500 + 1e-501e-5 + + + + + 1.2 + + 320 + 240 + R8G8B8 + + 0.150 + + 1 + 60 + false + + + /uav + image_raw:=camera/downward/image_raw + camera_info:=camera/downward/camera_info + + downward_camera + downward_camera_link + + + + + base_link + downward_camera_link + + + + + 127.0.0.1 + 9002 + 9003 + 0 0 0 3.141593 0 0 + 0 0 0 3.141593 0 0 + iris_with_ardupilot::base_link::imu_sensor + 5 + + + + rotor_0_joint + VELOCITY + 0 + 0.20 + 0 + 0 + 0 + 0 + 2.5 + -2.5 + 838 + + + rotor_1_joint + VELOCITY + 0 + 0.20 + 0 + 0 + 0 + 0 + 2.5 + -2.5 + 838 + + + rotor_2_joint + VELOCITY + 0 + 0.20 + 0 + 0 + 0 + 0 + 2.5 + -2.5 + -838 + + + rotor_3_joint + VELOCITY + 0 + 0.20 + 0 + 0 + 0 + 0 + 2.5 + -2.5 + -838 + + + + diff --git a/models/iris_with_camera/model.sdf b/models/iris_with_camera/model.sdf index f7917bf..f5252bf 100644 --- a/models/iris_with_camera/model.sdf +++ b/models/iris_with_camera/model.sdf @@ -1,24 +1,90 @@ + - - model://iris - + 0 0 0.1 0 0 0 - - 0.1 0 0 0 0 0 + + - 0.01 + 1.5 - 0.0000100 - 0.0000100.00001 + 0.02912500 + 0.02912500.055225 - - 0.02 0.02 0.02 + + + + + 0.3 0.3 0.1 + + + 0.2 0.2 0.8 1 + 0.2 0.2 0.8 1 + + + + + + 0.3 0.3 0.1 + + + + + + 0.15 0.15 0 0 0 0.785 + 0.3 0.02 0.02 + 0.3 0.3 0.3 1 + + + -0.15 0.15 0 0 0 -0.785 + 0.3 0.02 0.02 + 0.3 0.3 0.3 1 + + + -0.15 -0.15 0 0 0 0.785 + 0.3 0.02 0.02 + 0.3 0.3 0.3 1 + + + 0.15 -0.15 0 0 0 -0.785 + 0.3 0.02 0.02 + 0.3 0.3 0.3 1 + + + + + 0.22 0.22 0.05 0 0 0 + 0.10.01 + 0.1 0.1 0.1 1 + + + -0.22 0.22 0.05 0 0 0 + 0.10.01 + 0.1 0.1 0.1 1 + + + -0.22 -0.22 0.05 0 0 0 + 0.10.01 + 0.1 0.1 0.1 1 + + + 0.22 -0.22 0.05 0 0 0 + 0.10.01 + 0.1 0.1 0.1 1 + + + + + 0.18 0 0 0 0 0 + 0.03 0.03 0.03 0 0 0 1 + + + 0.18 0 0 0 0 0 1.57 @@ -31,37 +97,11 @@ 1 30 true - - - /uav - image_raw:=camera/forward/image_raw - camera_info:=camera/forward/camera_info - - forward_camera - forward_camera_link - - - - - iris::base_link - forward_camera_link - - - - 0 0 -0.05 0 1.5708 0 - - 0.01 - - 0.0000100 - 0.0000100.00001 - - - - 0.02 0.02 0.02 - 0.3 0.3 0.3 1 - + + + 0 0 -0.06 0 1.5708 0 1.2 @@ -74,55 +114,7 @@ 1 30 false - - - /uav - image_raw:=camera/downward/image_raw - camera_info:=camera/downward/camera_info - - downward_camera - downward_camera_link - - - - iris::base_link - downward_camera_link - - - - 0 0 -0.06 0 1.5708 0 - - 0.005 - - 0.00000100 - 0.00000100.000001 - - - - - - 1100 - - 0.1100.01 - - 1 - 30 - - - /uav - ~/out:=rangefinder/range - - sensor_msgs/Range - rangefinder_link - - - - - - iris::base_link - rangefinder_link - diff --git a/scripts/run_simulation.sh b/scripts/run_simulation.sh index c93743b..206ba28 100755 --- a/scripts/run_simulation.sh +++ b/scripts/run_simulation.sh @@ -1,7 +1,9 @@ #!/bin/bash +# Full simulation launch script with ArduPilot SITL +# This script launches Gazebo, ArduPilot SITL, and MAVROS + set -e -# Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' @@ -35,16 +37,26 @@ done if [ -z "$ROS_DISTRO" ]; then echo -e "${RED}ERROR: No ROS 2 installation found!${NC}" - echo "Please install ROS 2 first. See docs/setup_guide.md or docs/wsl_setup_guide.md" + echo "Please install ROS 2 first. See docs/setup_guide.md" exit 1 fi echo -e "${GREEN}Using ROS 2: $ROS_DISTRO${NC}" -# Source ROS 2 +# Check ArduPilot installation +ARDUPILOT_HOME="${ARDUPILOT_HOME:-$HOME/ardupilot}" +if [ ! -d "$ARDUPILOT_HOME" ]; then + echo -e "${RED}ERROR: ArduPilot not found at $ARDUPILOT_HOME${NC}" + echo "" + echo "Please install ArduPilot first:" + echo " bash scripts/install_ardupilot.sh" + echo "" + exit 1 +fi + +# Source environments source /opt/ros/${ROS_DISTRO}/setup.bash -# Source Gazebo setup (CRITICAL for shader paths) if [ -f /usr/share/gazebo/setup.bash ]; then source /usr/share/gazebo/setup.bash elif [ -f /usr/share/gazebo-11/setup.bash ]; then @@ -52,9 +64,10 @@ elif [ -f /usr/share/gazebo-11/setup.bash ]; then fi # Parse arguments -WORLD="" +WORLD="$PROJECT_DIR/worlds/iris_runway.world" +VEHICLE="copter" USE_SOFTWARE_RENDER=false -HEADLESS=false +INSTANCE=0 while [[ $# -gt 0 ]]; do case $1 in @@ -62,34 +75,32 @@ while [[ $# -gt 0 ]]; do WORLD="$2" shift 2 ;; - --headless) - HEADLESS=true - shift + --vehicle) + VEHICLE="$2" + shift 2 ;; - --no-gpu|--software-render) + --software-render) USE_SOFTWARE_RENDER=true shift ;; + --instance) + INSTANCE="$2" + shift 2 + ;; --help) - echo "Usage: $0 [OPTIONS] [WORLD_FILE]" + echo "Usage: $0 [OPTIONS]" echo "" echo "Options:" - echo " --world FILE Specify world file (default: empty_custom.world)" - echo " --headless Run without GUI (gzserver only)" - echo " --software-render Force software rendering (recommended for WSL)" - echo " --help Show this help" - echo "" - echo "Examples:" - echo " $0 # Default world" - echo " $0 worlds/indoor_warehouse.world # Indoor environment" - echo " $0 --software-render # For WSL without GPU" + echo " --world FILE World file (default: iris_runway.world)" + echo " --vehicle TYPE Vehicle type: copter, rover (default: copter)" + echo " --software-render Force software rendering (for WSL)" + echo " --instance N Vehicle instance number (default: 0)" + echo " --help Show this help" exit 0 ;; *) if [ -f "$1" ]; then WORLD="$1" - elif [ -f "$PROJECT_DIR/$1" ]; then - WORLD="$PROJECT_DIR/$1" elif [ -f "$PROJECT_DIR/worlds/$1" ]; then WORLD="$PROJECT_DIR/worlds/$1" fi @@ -98,109 +109,172 @@ while [[ $# -gt 0 ]]; do esac done -# Default world -if [ -z "$WORLD" ]; then - WORLD="$PROJECT_DIR/worlds/empty_custom.world" -fi - -# Validate world file -if [ ! -f "$WORLD" ]; then - echo -e "${RED}ERROR: World file not found: $WORLD${NC}" - echo "Available worlds:" - ls -1 "$PROJECT_DIR/worlds/"*.world 2>/dev/null || echo " (none found)" - exit 1 -fi - # Setup Gazebo paths export GAZEBO_MODEL_PATH="$PROJECT_DIR/models:${GAZEBO_MODEL_PATH:-}" export GAZEBO_RESOURCE_PATH="$PROJECT_DIR/worlds:${GAZEBO_RESOURCE_PATH:-}" -# ArduPilot Gazebo paths (if installed) if [ -d "$HOME/ardupilot_gazebo" ]; then export GAZEBO_MODEL_PATH="$HOME/ardupilot_gazebo/models:$GAZEBO_MODEL_PATH" export GAZEBO_RESOURCE_PATH="$HOME/ardupilot_gazebo/worlds:$GAZEBO_RESOURCE_PATH" fi -# WSL-specific setup +# WSL/Display setup if $IS_WSL; then - # Source WSL environment if exists if [ -f "$PROJECT_DIR/wsl_env.sh" ]; then source "$PROJECT_DIR/wsl_env.sh" fi - - # Set DISPLAY if not set if [ -z "$DISPLAY" ]; then - if [ -d "/mnt/wslg" ]; then - export DISPLAY=:0 - else - export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0 - fi + export DISPLAY=:0 fi - echo -e "${BLUE}DISPLAY: $DISPLAY${NC}" - - # Force software rendering in WSL by default if having issues - if ! $USE_SOFTWARE_RENDER; then - echo -e "${YELLOW}TIP: If Gazebo crashes or has rendering issues, use --software-render${NC}" - fi fi -# Apply software rendering if requested or in WSL with issues if $USE_SOFTWARE_RENDER; then echo -e "${YELLOW}Using software rendering${NC}" export LIBGL_ALWAYS_SOFTWARE=1 export MESA_GL_VERSION_OVERRIDE=3.3 - export MESA_GLSL_VERSION_OVERRIDE=330 fi # Cleanup function cleanup() { echo "" echo -e "${YELLOW}Shutting down simulation...${NC}" + + # Kill processes + pkill -f "sim_vehicle.py" 2>/dev/null || true + pkill -f "mavproxy" 2>/dev/null || true + pkill -f "ArduCopter" 2>/dev/null || true + pkill -f "ArduRover" 2>/dev/null || true pkill -f "gzserver" 2>/dev/null || true pkill -f "gzclient" 2>/dev/null || true pkill -f "gazebo" 2>/dev/null || true - sleep 1 + pkill -f "mavros" 2>/dev/null || true + + sleep 2 echo -e "${GREEN}Cleanup complete.${NC}" } trap cleanup EXIT INT TERM -# Activate virtual environment if exists +# Activate virtual environment if [ -f "$PROJECT_DIR/venv/bin/activate" ]; then source "$PROJECT_DIR/venv/bin/activate" fi -# Source workspace if built -if [ -f "$PROJECT_DIR/../install/setup.bash" ]; then - source "$PROJECT_DIR/../install/setup.bash" -elif [ -f "$PROJECT_DIR/install/setup.bash" ]; then - source "$PROJECT_DIR/install/setup.bash" -fi - -echo "" -echo -e "${GREEN}Starting simulation with world: $(basename $WORLD)${NC}" -echo -e "${BLUE}World path: $WORLD${NC}" -echo "" - -# Check if ROS package exists -ROS_PKG_EXISTS=false -if ros2 pkg list 2>/dev/null | grep -q "uav_ugv_simulation"; then - ROS_PKG_EXISTS=true -fi - -# Launch simulation -if $ROS_PKG_EXISTS; then - echo -e "${GREEN}Launching via ROS 2...${NC}" - ros2 launch uav_ugv_simulation full_simulation.launch.py world:="$WORLD" -else - echo -e "${YELLOW}ROS package not built. Launching Gazebo directly...${NC}" - echo -e "${BLUE}To build the package: cd ~/ros2_ws && colcon build --packages-select uav_ugv_simulation${NC}" - echo "" - - if $HEADLESS; then - gzserver --verbose "$WORLD" +# Use ardupilot_gazebo iris world if no custom world specified +if [ ! -f "$WORLD" ]; then + if [ -f "$HOME/ardupilot_gazebo/worlds/iris_arducopter_runway.world" ]; then + WORLD="$HOME/ardupilot_gazebo/worlds/iris_arducopter_runway.world" else - gazebo --verbose "$WORLD" + echo -e "${RED}ERROR: World file not found: $WORLD${NC}" + exit 1 fi fi + +echo "" +echo -e "${GREEN}Configuration:${NC}" +echo " Vehicle: $VEHICLE" +echo " World: $(basename $WORLD)" +echo " Instance: $INSTANCE" +echo "" + +# Calculate ports +MAVLINK_PORT=$((14550 + INSTANCE * 10)) +SITL_PORT=$((5760 + INSTANCE * 10)) + +# Start Gazebo in background +echo -e "${GREEN}Starting Gazebo...${NC}" +gazebo --verbose "$WORLD" & +GAZEBO_PID=$! + +sleep 5 + +# Check if Gazebo started +if ! kill -0 $GAZEBO_PID 2>/dev/null; then + echo -e "${RED}ERROR: Gazebo failed to start${NC}" + exit 1 +fi + +echo -e "${GREEN}Gazebo running (PID: $GAZEBO_PID)${NC}" + +# Start ArduPilot SITL +echo -e "${GREEN}Starting ArduPilot SITL...${NC}" +cd "$ARDUPILOT_HOME" + +if [ "$VEHICLE" = "copter" ]; then + VEHICLE_DIR="ArduCopter" + FRAME="gazebo-iris" +elif [ "$VEHICLE" = "rover" ]; then + VEHICLE_DIR="Rover" + FRAME="gazebo-rover" +else + VEHICLE_DIR="ArduCopter" + FRAME="gazebo-iris" +fi + +cd "$ARDUPILOT_HOME/$VEHICLE_DIR" + +# Start sim_vehicle.py in background +python3 "$ARDUPILOT_HOME/Tools/autotest/sim_vehicle.py" \ + -v "$VEHICLE_DIR" \ + -f "$FRAME" \ + --no-mavproxy \ + -I "$INSTANCE" \ + --no-rebuild \ + & +SITL_PID=$! + +sleep 10 + +# Check if SITL started +if ! kill -0 $SITL_PID 2>/dev/null; then + echo -e "${RED}ERROR: ArduPilot SITL failed to start${NC}" + exit 1 +fi + +echo -e "${GREEN}ArduPilot SITL running (PID: $SITL_PID)${NC}" + +# Start MAVROS +echo -e "${GREEN}Starting MAVROS...${NC}" +ros2 run mavros mavros_node --ros-args \ + -p fcu_url:="udp://127.0.0.1:${MAVLINK_PORT}@" \ + -p gcs_url:="" \ + -p target_system_id:=1 \ + -p target_component_id:=1 \ + &>/dev/null & +MAVROS_PID=$! + +sleep 5 + +echo "" +echo -e "${GREEN}==========================================${NC}" +echo -e "${GREEN} Simulation Running${NC}" +echo -e "${GREEN}==========================================${NC}" +echo "" +echo -e "${BLUE}Components:${NC}" +echo " - Gazebo: PID $GAZEBO_PID" +echo " - ArduPilot SITL: PID $SITL_PID" +echo " - MAVROS: PID $MAVROS_PID" +echo "" +echo -e "${BLUE}MAVROS Topics:${NC}" +echo " ros2 topic list | grep mavros" +echo "" +echo -e "${BLUE}Control UAV:${NC}" +echo " # Arm" +echo " ros2 service call /mavros/cmd/arming mavros_msgs/srv/CommandBool \"{value: true}\"" +echo "" +echo " # Set mode to GUIDED" +echo " ros2 service call /mavros/set_mode mavros_msgs/srv/SetMode \"{base_mode: 0, custom_mode: 'GUIDED'}\"" +echo "" +echo " # Takeoff to 5 meters" +echo " ros2 service call /mavros/cmd/takeoff mavros_msgs/srv/CommandTOL \"{altitude: 5}\"" +echo "" +echo " # Send position setpoint (x, y, z in meters)" +echo " ros2 topic pub /mavros/setpoint_position/local geometry_msgs/PoseStamped \\" +echo " \"{header: {frame_id: 'map'}, pose: {position: {x: 10, y: 5, z: 5}}}\"" +echo "" +echo -e "${YELLOW}Press Ctrl+C to stop simulation${NC}" +echo "" + +# Wait for all processes +wait diff --git a/scripts/setup_gazebo_nvidia.sh b/scripts/setup_gazebo_nvidia.sh deleted file mode 100755 index 8257265..0000000 --- a/scripts/setup_gazebo_nvidia.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -echo "Setting up NVIDIA GPU for Gazebo..." - -if ! command -v nvidia-smi &> /dev/null; then - echo "NVIDIA driver not found. Skipping GPU setup." - exit 0 -fi - -echo "NVIDIA GPU detected:" -nvidia-smi --query-gpu=name,driver_version --format=csv,noheader - -export __NV_PRIME_RENDER_OFFLOAD=1 -export __GLX_VENDOR_LIBRARY_NAME=nvidia -export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json - -if [ -f /usr/lib/x86_64-linux-gnu/libEGL_nvidia.so.0 ]; then - export __EGL_VENDOR_LIBRARY_FILENAMES=/usr/share/glvnd/egl_vendor.d/10_nvidia.json -fi - -echo "NVIDIA GPU environment configured." -echo "" -echo "Add these to your ~/.bashrc for permanent setup:" -echo " export __NV_PRIME_RENDER_OFFLOAD=1" -echo " export __GLX_VENDOR_LIBRARY_NAME=nvidia" diff --git a/scripts/setup_wsl.sh b/scripts/setup_wsl.sh deleted file mode 100755 index 20ae761..0000000 --- a/scripts/setup_wsl.sh +++ /dev/null @@ -1,174 +0,0 @@ -#!/bin/bash -# WSL Quick Setup Script -# This script sets up the simulation environment specifically for WSL2 - -set -e - -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' - -echo -e "${BLUE}==========================================${NC}" -echo -e "${BLUE} UAV-UGV Simulation - WSL Setup${NC}" -echo -e "${BLUE}==========================================${NC}" -echo "" - -# Check if running in WSL -if ! grep -qEi "(microsoft|wsl)" /proc/version 2>/dev/null; then - echo -e "${YELLOW}This script is designed for WSL. Running anyway...${NC}" -fi - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_DIR="$(dirname "$SCRIPT_DIR")" - -# Detect Ubuntu version -. /etc/os-release -echo -e "${BLUE}Detected: Ubuntu $VERSION_ID ($VERSION_CODENAME)${NC}" - -# Determine ROS distro -case "$VERSION_ID" in - "22.04") ROS_DISTRO="humble" ;; - "24.04") ROS_DISTRO="jazzy" ;; - *) ROS_DISTRO="humble"; echo -e "${YELLOW}Unknown Ubuntu version, defaulting to Humble${NC}" ;; -esac - -echo -e "${BLUE}Target ROS 2 distro: $ROS_DISTRO${NC}" -echo "" - -# Step 1: Update and install prerequisites -echo -e "${GREEN}[1/6] Installing prerequisites...${NC}" -sudo apt-get update -sudo apt-get install -y \ - software-properties-common \ - curl \ - gnupg \ - lsb-release \ - x11-apps \ - x11-xserver-utils \ - dbus-x11 \ - mesa-utils \ - libgl1-mesa-glx - -# Step 2: Add ROS 2 repository -echo -e "${GREEN}[2/6] Adding ROS 2 repository...${NC}" -if [ ! -f /usr/share/keyrings/ros-archive-keyring.gpg ]; then - sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key \ - -o /usr/share/keyrings/ros-archive-keyring.gpg -fi - -if [ ! -f /etc/apt/sources.list.d/ros2.list ]; then - echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] \ - http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main" | \ - sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null -fi - -sudo apt-get update - -# Step 3: Install ROS 2 -echo -e "${GREEN}[3/6] Installing ROS 2 $ROS_DISTRO...${NC}" -if [ ! -d "/opt/ros/$ROS_DISTRO" ]; then - sudo apt-get install -y ros-${ROS_DISTRO}-desktop python3-colcon-common-extensions || { - echo -e "${YELLOW}Desktop install failed, trying base...${NC}" - sudo apt-get install -y ros-${ROS_DISTRO}-ros-base - } -else - echo -e "${BLUE}ROS 2 $ROS_DISTRO already installed${NC}" -fi - -# Step 4: Install ROS packages -echo -e "${GREEN}[4/6] Installing ROS 2 packages...${NC}" -sudo apt-get install -y \ - ros-${ROS_DISTRO}-mavros \ - ros-${ROS_DISTRO}-mavros-extras \ - ros-${ROS_DISTRO}-cv-bridge \ - ros-${ROS_DISTRO}-image-transport \ - ros-${ROS_DISTRO}-tf2-ros 2>/dev/null || { - echo -e "${YELLOW}Some packages unavailable for $ROS_DISTRO${NC}" -} - -# Gazebo (different for Humble vs Jazzy) -if [ "$ROS_DISTRO" = "humble" ]; then - sudo apt-get install -y ros-humble-gazebo-ros-pkgs 2>/dev/null || true -elif [ "$ROS_DISTRO" = "jazzy" ]; then - sudo apt-get install -y ros-jazzy-ros-gz 2>/dev/null || true -fi - -# GeographicLib datasets -echo -e "${GREEN}[5/6] Installing GeographicLib datasets...${NC}" -GEOGRAPHICLIB_SCRIPT="/opt/ros/${ROS_DISTRO}/lib/mavros/install_geographiclib_datasets.sh" -if [ -f "$GEOGRAPHICLIB_SCRIPT" ] && [ ! -f /usr/share/GeographicLib/geoids/egm96-5.pgm ]; then - sudo "$GEOGRAPHICLIB_SCRIPT" || echo -e "${YELLOW}GeographicLib install failed${NC}" -fi - -# Step 5: Setup Python environment -echo -e "${GREEN}[6/6] Setting up Python environment...${NC}" -cd "$PROJECT_DIR" - -sudo apt-get install -y python3-pip python3-venv python3-opencv libopencv-dev - -if [ ! -d "venv" ]; then - python3 -m venv venv -fi - -source venv/bin/activate -pip install --upgrade pip -pip install -r requirements.txt 2>/dev/null || echo -e "${YELLOW}Some pip packages failed${NC}" - -# Create WSL environment file -cat > "$PROJECT_DIR/wsl_env.sh" << 'EOF' -#!/bin/bash -# WSL Environment Setup - -# DISPLAY configuration -if [ -d "/mnt/wslg" ]; then - # WSLg (Windows 11) - export DISPLAY=:0 -else - # X server (Windows 10) - export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0 -fi - -# OpenGL settings for WSL -export LIBGL_ALWAYS_INDIRECT=0 -export MESA_GL_VERSION_OVERRIDE=3.3 - -# Uncomment for software rendering if GPU issues: -# export LIBGL_ALWAYS_SOFTWARE=1 - -# Gazebo performance -export OGRE_RTT_MODE=Copy -EOF -chmod +x "$PROJECT_DIR/wsl_env.sh" - -# Add to bashrc -if ! grep -q "wsl_env.sh" ~/.bashrc 2>/dev/null; then - echo "" >> ~/.bashrc - echo "# UAV-UGV Simulation WSL environment" >> ~/.bashrc - echo "[ -f \"$PROJECT_DIR/wsl_env.sh\" ] && source \"$PROJECT_DIR/wsl_env.sh\"" >> ~/.bashrc - echo "[ -f /opt/ros/${ROS_DISTRO}/setup.bash ] && source /opt/ros/${ROS_DISTRO}/setup.bash" >> ~/.bashrc -fi - -# Make scripts executable -chmod +x "$PROJECT_DIR/scripts/"*.sh 2>/dev/null || true -chmod +x "$PROJECT_DIR/setup.sh" 2>/dev/null || true -chmod +x "$PROJECT_DIR/activate_venv.sh" 2>/dev/null || true - -echo "" -echo -e "${GREEN}==========================================${NC}" -echo -e "${GREEN} WSL Setup Complete!${NC}" -echo -e "${GREEN}==========================================${NC}" -echo "" -echo -e "${BLUE}Next steps:${NC}" -echo " 1. Close and reopen your terminal (or run: source ~/.bashrc)" -echo " 2. Test GUI: xcalc (should open calculator)" -echo " 3. Test Gazebo: gazebo --verbose" -echo " 4. Run simulation: source activate_venv.sh && bash scripts/run_simulation.sh" -echo "" -echo -e "${YELLOW}WSL Tips:${NC}" -echo " - Windows 11: GUI works out of the box (WSLg)" -echo " - Windows 10: Install VcXsrv and run XLaunch first" -echo " - Slow graphics? Run with: bash scripts/run_simulation.sh --software-render" -echo " - See docs/wsl_setup_guide.md for detailed help" -echo "" diff --git a/setup.sh b/setup.sh index 2225717..e4cfd8b 100755 --- a/setup.sh +++ b/setup.sh @@ -1,17 +1,21 @@ #!/bin/bash +# UAV-UGV Simulation - Complete Installation Script +# Installs everything needed for GPS-denied navigation simulation +# Compatible with Ubuntu 22.04/24.04 and WSL2 + set -e -# Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' -NC='\033[0m' # No Color +CYAN='\033[0;36m' +NC='\033[0m' print_header() { + echo "" echo -e "${BLUE}==========================================${NC}" - echo -e "${BLUE} UAV-UGV Simulation Setup${NC}" - echo -e "${BLUE} GPS-Denied Navigation with Geofencing${NC}" + echo -e "${BLUE} $1${NC}" echo -e "${BLUE}==========================================${NC}" echo "" } @@ -20,6 +24,10 @@ print_step() { echo -e "${GREEN}[$1/$TOTAL_STEPS] $2${NC}" } +print_info() { + echo -e "${CYAN}INFO: $1${NC}" +} + print_warning() { echo -e "${YELLOW}WARNING: $1${NC}" } @@ -28,21 +36,14 @@ print_error() { echo -e "${RED}ERROR: $1${NC}" } -print_info() { - echo -e "${BLUE}INFO: $1${NC}" -} - # Detect environment detect_environment() { IS_WSL=false IS_WSL2=false - UBUNTU_VERSION="" - ROS_DISTRO="" - # Detect WSL if grep -qEi "(microsoft|wsl)" /proc/version 2>/dev/null; then IS_WSL=true - if grep -qi "wsl2" /proc/version 2>/dev/null || [ -f /run/WSL ]; then + if [ -f /run/WSL ] || grep -qi "wsl2" /proc/version 2>/dev/null; then IS_WSL2=true fi fi @@ -54,330 +55,319 @@ detect_environment() { UBUNTU_CODENAME="$VERSION_CODENAME" fi - # Determine ROS distro based on Ubuntu version + # Determine ROS distro case "$UBUNTU_VERSION" in - "22.04") - ROS_DISTRO="humble" - ;; - "24.04") - ROS_DISTRO="jazzy" - ;; - "20.04") - ROS_DISTRO="galactic" - ;; - *) - ROS_DISTRO="humble" # Default fallback - ;; + "22.04") ROS_DISTRO="humble" ;; + "24.04") ROS_DISTRO="jazzy" ;; + "20.04") ROS_DISTRO="galactic" ;; + *) ROS_DISTRO="humble" ;; esac - - echo -e "${BLUE}Detected Environment:${NC}" - echo " - Ubuntu: $UBUNTU_VERSION ($UBUNTU_CODENAME)" - echo " - WSL: $IS_WSL" - echo " - WSL2: $IS_WSL2" - echo " - ROS 2 Distro: $ROS_DISTRO" - echo "" } -# Check if ROS 2 is installed -check_ros2_installed() { - if [ -d "/opt/ros/$ROS_DISTRO" ]; then - return 0 - else - return 1 +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR" + +print_header "UAV-UGV Simulation - Complete Setup" +echo "GPS-Denied Navigation with Geofencing" +echo "" + +detect_environment + +echo -e "${CYAN}Detected Environment:${NC}" +echo " Ubuntu: $UBUNTU_VERSION ($UBUNTU_CODENAME)" +echo " WSL: $IS_WSL | WSL2: $IS_WSL2" +echo " ROS 2 Target: $ROS_DISTRO" +echo "" + +TOTAL_STEPS=10 +STEP=1 + +# ============================================================================ +# STEP 1: System Update +# ============================================================================ +print_step $STEP "Updating system packages" +sudo apt-get update +sudo apt-get upgrade -y +((STEP++)) + +# ============================================================================ +# STEP 2: Install Base Dependencies +# ============================================================================ +print_step $STEP "Installing base dependencies" +sudo apt-get install -y \ + curl \ + gnupg \ + lsb-release \ + software-properties-common \ + wget \ + git \ + gitk \ + build-essential \ + cmake \ + python3-dev \ + python3-pip \ + python3-venv \ + python3-opencv \ + python3-matplotlib \ + python3-lxml \ + python3-yaml \ + python3-scipy \ + python3-future \ + libopencv-dev \ + libxml2-dev \ + libxslt1-dev \ + ccache \ + gawk \ + libtool-bin + +# WSL-specific packages +if $IS_WSL; then + print_info "Installing WSL GUI support packages" + sudo apt-get install -y \ + x11-apps \ + x11-xserver-utils \ + dbus-x11 \ + mesa-utils \ + libgl1-mesa-glx +fi +((STEP++)) + +# ============================================================================ +# STEP 3: Install ROS 2 +# ============================================================================ +print_step $STEP "Installing ROS 2 $ROS_DISTRO" + +if [ ! -d "/opt/ros/$ROS_DISTRO" ]; then + # Add ROS 2 repository + if [ ! -f /usr/share/keyrings/ros-archive-keyring.gpg ]; then + sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key \ + -o /usr/share/keyrings/ros-archive-keyring.gpg fi -} - -# Install ROS 2 repository -install_ros2_repo() { - print_info "Setting up ROS 2 repository..." - sudo apt-get install -y software-properties-common curl gnupg lsb-release - - # Add ROS 2 GPG key - sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key \ - -o /usr/share/keyrings/ros-archive-keyring.gpg - - # Add repository echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] \ http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main" | \ sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null sudo apt-get update -} - -# Setup WSL-specific configurations -setup_wsl() { - print_info "Configuring WSL-specific settings..." - - # Create WSL environment setup - WSL_ENV_FILE="$SCRIPT_DIR/wsl_env.sh" - - cat > "$WSL_ENV_FILE" << 'WSLEOF' -#!/bin/bash -# WSL-specific environment variables - -# Detect WSL version and set DISPLAY -if grep -qi "wsl2" /proc/version 2>/dev/null || [ -f /run/WSL ]; then - # WSL2 with WSLg (Windows 11) - if [ -d "/mnt/wslg" ]; then - export DISPLAY=:0 - else - # WSL2 without WSLg (Windows 10) - use X server - export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0 - fi + sudo apt-get install -y ros-${ROS_DISTRO}-desktop python3-colcon-common-extensions else - # WSL1 - export DISPLAY=localhost:0 + print_info "ROS 2 $ROS_DISTRO already installed" fi - -# Performance settings for Gazebo in WSL -export LIBGL_ALWAYS_INDIRECT=0 - -# If GPU acceleration isn't working, uncomment this: -# export LIBGL_ALWAYS_SOFTWARE=1 - -# Mesa driver settings (helps with some rendering issues) -export MESA_GL_VERSION_OVERRIDE=3.3 -export MESA_GLSL_VERSION_OVERRIDE=330 - -# Gazebo specific -export OGRE_RTT_MODE=Copy -WSLEOF - - chmod +x "$WSL_ENV_FILE" - - # Add to bashrc if not already present - if ! grep -q "wsl_env.sh" ~/.bashrc 2>/dev/null; then - echo "" >> ~/.bashrc - echo "# WSL environment for UAV-UGV simulation" >> ~/.bashrc - echo "if [ -f \"$WSL_ENV_FILE\" ]; then source \"$WSL_ENV_FILE\"; fi" >> ~/.bashrc - fi - - print_info "WSL environment configured. Source ~/.bashrc to apply." -} - -# Setup X11 for GUI applications -setup_x11_wsl() { - print_info "Installing X11 utilities for GUI support..." - - sudo apt-get install -y \ - x11-apps \ - x11-xserver-utils \ - dbus-x11 \ - libgl1-mesa-glx \ - mesa-utils 2>/dev/null || true -} - -# Main setup -print_header - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -cd "$SCRIPT_DIR" - -# Detect environment -detect_environment - -# Determine total steps based on what's needed -if check_ros2_installed; then - TOTAL_STEPS=7 -else - TOTAL_STEPS=9 - print_warning "ROS 2 $ROS_DISTRO not found. Will attempt to install." -fi - -if $IS_WSL; then - TOTAL_STEPS=$((TOTAL_STEPS + 1)) -fi - -STEP=1 - -# Step: Update system -print_step $STEP "Updating system packages..." -sudo apt-get update ((STEP++)) -# Step: WSL-specific setup -if $IS_WSL; then - print_step $STEP "Setting up WSL environment..." - setup_wsl - setup_x11_wsl - ((STEP++)) -fi - -# Step: Install ROS 2 if not present -if ! check_ros2_installed; then - print_step $STEP "Installing ROS 2 repository..." - install_ros2_repo - ((STEP++)) - - print_step $STEP "Installing ROS 2 $ROS_DISTRO..." - sudo apt-get install -y ros-${ROS_DISTRO}-desktop || { - print_warning "Failed to install ros-${ROS_DISTRO}-desktop, trying base..." - sudo apt-get install -y ros-${ROS_DISTRO}-ros-base - } - ((STEP++)) -fi - -# Step: Install system dependencies -print_step $STEP "Installing system dependencies..." +# ============================================================================ +# STEP 4: Install ROS 2 Packages +# ============================================================================ +print_step $STEP "Installing ROS 2 packages" sudo apt-get install -y \ - python3-pip \ - python3-venv \ - python3-opencv \ - libopencv-dev \ - python3-colcon-common-extensions \ - build-essential \ - cmake \ - git || true -((STEP++)) + ros-${ROS_DISTRO}-mavros \ + ros-${ROS_DISTRO}-mavros-extras \ + ros-${ROS_DISTRO}-cv-bridge \ + ros-${ROS_DISTRO}-image-transport \ + ros-${ROS_DISTRO}-tf2 \ + ros-${ROS_DISTRO}-tf2-ros \ + ros-${ROS_DISTRO}-tf2-geometry-msgs \ + ros-${ROS_DISTRO}-gazebo-ros-pkgs 2>/dev/null || \ + print_warning "Some ROS packages not available for $ROS_DISTRO" -# Step: Install ROS 2 packages -print_step $STEP "Installing ROS 2 packages..." -ROS_PACKAGES=( - "ros-${ROS_DISTRO}-mavros" - "ros-${ROS_DISTRO}-mavros-extras" - "ros-${ROS_DISTRO}-cv-bridge" - "ros-${ROS_DISTRO}-image-transport" - "ros-${ROS_DISTRO}-tf2" - "ros-${ROS_DISTRO}-tf2-ros" - "ros-${ROS_DISTRO}-tf2-geometry-msgs" -) - -# Gazebo packages differ by distro -if [ "$ROS_DISTRO" = "humble" ]; then - ROS_PACKAGES+=("ros-${ROS_DISTRO}-gazebo-ros-pkgs") -elif [ "$ROS_DISTRO" = "jazzy" ]; then - # Jazzy uses Gazebo Harmonic (gz-sim) - ROS_PACKAGES+=("ros-${ROS_DISTRO}-ros-gz") -fi - -# Install available packages (some may not exist for all distros) -for pkg in "${ROS_PACKAGES[@]}"; do - sudo apt-get install -y "$pkg" 2>/dev/null || { - print_warning "Package $pkg not available, skipping..." - } -done -((STEP++)) - -# Step: Install MAVROS GeographicLib datasets -print_step $STEP "Installing MAVROS GeographicLib datasets..." +# Install GeographicLib datasets for MAVROS GEOGRAPHICLIB_SCRIPT="/opt/ros/${ROS_DISTRO}/lib/mavros/install_geographiclib_datasets.sh" if [ -f "$GEOGRAPHICLIB_SCRIPT" ]; then if [ ! -f /usr/share/GeographicLib/geoids/egm96-5.pgm ]; then - sudo "$GEOGRAPHICLIB_SCRIPT" || print_warning "GeographicLib datasets installation failed" - else - print_info "GeographicLib datasets already installed" + print_info "Installing GeographicLib datasets (this may take a minute)" + sudo "$GEOGRAPHICLIB_SCRIPT" || print_warning "GeographicLib installation failed" fi -else - print_warning "MAVROS not installed, skipping GeographicLib datasets" fi ((STEP++)) -# Step: Create Python virtual environment -print_step $STEP "Creating Python virtual environment..." +# ============================================================================ +# STEP 5: Install Gazebo +# ============================================================================ +print_step $STEP "Installing Gazebo" +sudo apt-get install -y gazebo libgazebo-dev || \ +sudo apt-get install -y gazebo11 libgazebo11-dev || \ +print_warning "Gazebo installation may require manual setup" +((STEP++)) + +# ============================================================================ +# STEP 6: Install ArduPilot SITL +# ============================================================================ +print_step $STEP "Installing ArduPilot SITL" + +ARDUPILOT_HOME="$HOME/ardupilot" +if [ ! -d "$ARDUPILOT_HOME" ]; then + print_info "Cloning ArduPilot repository..." + cd "$HOME" + git clone --recurse-submodules https://github.com/ArduPilot/ardupilot.git + cd ardupilot + git submodule update --init --recursive +else + print_info "ArduPilot already exists, updating..." + cd "$ARDUPILOT_HOME" + git fetch origin + git submodule update --init --recursive +fi + +# Install ArduPilot prerequisites +print_info "Installing ArduPilot prerequisites..." +cd "$ARDUPILOT_HOME" +USER_NONINTERACTIVE=1 Tools/environment_install/install-prereqs-ubuntu.sh -y || true + +# Reload profile +. ~/.profile 2>/dev/null || true + +# Build ArduPilot SITL +print_info "Building ArduPilot SITL (this may take several minutes)..." +cd "$ARDUPILOT_HOME" +./waf configure --board sitl +./waf copter +./waf rover +((STEP++)) + +# ============================================================================ +# STEP 7: Install ardupilot_gazebo Plugin +# ============================================================================ +print_step $STEP "Installing ardupilot_gazebo plugin" + +ARDUPILOT_GAZEBO_HOME="$HOME/ardupilot_gazebo" +if [ ! -d "$ARDUPILOT_GAZEBO_HOME" ]; then + print_info "Cloning ardupilot_gazebo..." + cd "$HOME" + git clone https://github.com/ArduPilot/ardupilot_gazebo.git +else + print_info "ardupilot_gazebo already exists, updating..." + cd "$ARDUPILOT_GAZEBO_HOME" + git pull origin main || true +fi + +cd "$ARDUPILOT_GAZEBO_HOME" +mkdir -p build && cd build +cmake .. +make -j$(nproc) +sudo make install +((STEP++)) + +# ============================================================================ +# STEP 8: Setup Python Virtual Environment +# ============================================================================ +print_step $STEP "Setting up Python environment" + +cd "$SCRIPT_DIR" + if [ ! -d "venv" ]; then python3 -m venv venv fi + source venv/bin/activate - -# Upgrade pip and install dependencies pip install --upgrade pip -pip install -r requirements.txt || { - print_warning "Some Python packages failed to install. Check requirements.txt" -} +pip install -r requirements.txt || print_warning "Some Python packages failed" +deactivate ((STEP++)) -# Step: Build ROS 2 package -print_step $STEP "Building ROS 2 package..." -if [ -f "/opt/ros/${ROS_DISTRO}/setup.bash" ]; then - source /opt/ros/${ROS_DISTRO}/setup.bash - - # Try to build if in a ROS workspace - if [ -d "$SCRIPT_DIR/../src" ] || [ -f "$SCRIPT_DIR/package.xml" ]; then - cd "$SCRIPT_DIR/.." - colcon build --packages-select uav_ugv_simulation --symlink-install 2>/dev/null || { - print_warning "Colcon build skipped. To build manually:" - print_info " cd ~/ros2_ws && colcon build --packages-select uav_ugv_simulation" - } - cd "$SCRIPT_DIR" - fi +# ============================================================================ +# STEP 9: Configure Environment +# ============================================================================ +print_step $STEP "Configuring environment" + +# Create WSL environment file +if $IS_WSL; then + cat > "$SCRIPT_DIR/wsl_env.sh" << 'WSLEOF' +#!/bin/bash +# WSL Environment for UAV-UGV Simulation + +if [ -d "/mnt/wslg" ]; then + export DISPLAY=:0 else - print_warning "ROS 2 not found, skipping package build" + export DISPLAY=$(cat /etc/resolv.conf 2>/dev/null | grep nameserver | awk '{print $2}'):0 fi -((STEP++)) -# Step: Make scripts executable and create activation script -print_step $STEP "Finalizing setup..." -chmod +x scripts/*.sh 2>/dev/null || true +export LIBGL_ALWAYS_INDIRECT=0 +export MESA_GL_VERSION_OVERRIDE=3.3 +export MESA_GLSL_VERSION_OVERRIDE=330 +export OGRE_RTT_MODE=Copy + +# Source Gazebo setup +[ -f /usr/share/gazebo/setup.bash ] && source /usr/share/gazebo/setup.bash +[ -f /usr/share/gazebo-11/setup.bash ] && source /usr/share/gazebo-11/setup.bash +WSLEOF + chmod +x "$SCRIPT_DIR/wsl_env.sh" +fi # Create activation script -cat > activate_venv.sh << EOF +cat > "$SCRIPT_DIR/activate_venv.sh" << EOF #!/bin/bash SCRIPT_DIR="\$(cd "\$(dirname "\${BASH_SOURCE[0]}")" && pwd)" -# Activate Python virtual environment +# ROS 2 +source /opt/ros/${ROS_DISTRO}/setup.bash + +# Gazebo +[ -f /usr/share/gazebo/setup.bash ] && source /usr/share/gazebo/setup.bash +[ -f /usr/share/gazebo-11/setup.bash ] && source /usr/share/gazebo-11/setup.bash + +# Python venv source "\$SCRIPT_DIR/venv/bin/activate" -# Source ROS 2 -if [ -f "/opt/ros/${ROS_DISTRO}/setup.bash" ]; then - source /opt/ros/${ROS_DISTRO}/setup.bash -fi - -# Source workspace if built -if [ -f "\$SCRIPT_DIR/../install/setup.bash" ]; then - source "\$SCRIPT_DIR/../install/setup.bash" -elif [ -f "\$SCRIPT_DIR/install/setup.bash" ]; then - source "\$SCRIPT_DIR/install/setup.bash" -fi - # Gazebo paths -export GAZEBO_MODEL_PATH="\$SCRIPT_DIR/models:\$GAZEBO_MODEL_PATH" -export GAZEBO_RESOURCE_PATH="\$SCRIPT_DIR/worlds:\$GAZEBO_RESOURCE_PATH" +export GAZEBO_MODEL_PATH="\$SCRIPT_DIR/models:\$HOME/ardupilot_gazebo/models:\${GAZEBO_MODEL_PATH:-}" +export GAZEBO_RESOURCE_PATH="\$SCRIPT_DIR/worlds:\$HOME/ardupilot_gazebo/worlds:\${GAZEBO_RESOURCE_PATH:-}" -# ArduPilot Gazebo (if installed) -if [ -d "\$HOME/ardupilot_gazebo" ]; then - export GAZEBO_MODEL_PATH="\$HOME/ardupilot_gazebo/models:\$GAZEBO_MODEL_PATH" - export GAZEBO_RESOURCE_PATH="\$HOME/ardupilot_gazebo/worlds:\$GAZEBO_RESOURCE_PATH" -fi +# ArduPilot +export PATH="\$PATH:\$HOME/ardupilot/Tools/autotest" +export ARDUPILOT_HOME="\$HOME/ardupilot" -# WSL environment (if applicable) -if [ -f "\$SCRIPT_DIR/wsl_env.sh" ]; then - source "\$SCRIPT_DIR/wsl_env.sh" +# WSL +if grep -qEi "(microsoft|wsl)" /proc/version 2>/dev/null; then + [ -f "\$SCRIPT_DIR/wsl_env.sh" ] && source "\$SCRIPT_DIR/wsl_env.sh" fi echo -e "\033[0;32mEnvironment activated (ROS 2 ${ROS_DISTRO})\033[0m" -echo "Run: bash scripts/run_simulation.sh" -EOF -chmod +x activate_venv.sh - -# Summary echo "" -echo -e "${GREEN}==========================================${NC}" -echo -e "${GREEN} Setup Complete!${NC}" -echo -e "${GREEN}==========================================${NC}" +echo "Run simulation: bash scripts/run_simulation.sh" +echo "With rendering: bash scripts/run_simulation.sh --software-render" +EOF +chmod +x "$SCRIPT_DIR/activate_venv.sh" + +((STEP++)) + +# ============================================================================ +# STEP 10: Make Scripts Executable +# ============================================================================ +print_step $STEP "Finalizing installation" +chmod +x "$SCRIPT_DIR/scripts/"*.sh 2>/dev/null || true +chmod +x "$SCRIPT_DIR/activate_venv.sh" 2>/dev/null || true +((STEP++)) + +# ============================================================================ +# COMPLETE +# ============================================================================ +print_header "Installation Complete!" + +echo -e "${GREEN}All components installed:${NC}" +echo " - ROS 2 $ROS_DISTRO" +echo " - Gazebo" +echo " - ArduPilot SITL ($ARDUPILOT_HOME)" +echo " - ardupilot_gazebo ($ARDUPILOT_GAZEBO_HOME)" +echo " - MAVROS" +echo " - Python dependencies" echo "" if $IS_WSL; then echo -e "${YELLOW}WSL Setup Notes:${NC}" - echo " - WSL environment file created: wsl_env.sh" - echo " - For GUI apps, ensure X server is running (Windows 11 has WSLg built-in)" - echo " - See docs/wsl_setup_guide.md for detailed instructions" + echo " - GUI apps require WSLg (Windows 11) or VcXsrv (Windows 10)" + echo " - Use --software-render flag if graphics are slow" echo "" fi -echo -e "${BLUE}Next steps:${NC}" -echo " 1. source ~/.bashrc" -echo " 2. source activate_venv.sh" -echo " 3. bash scripts/run_simulation.sh" +echo -e "${CYAN}To run the simulation:${NC}" echo "" -echo -e "${BLUE}GPS-Denied Navigation:${NC}" -echo " - All navigation uses LOCAL coordinates" -echo " - GPS is ONLY used for geofencing" +echo " cd $SCRIPT_DIR" +echo " source activate_venv.sh" +echo " bash scripts/run_simulation.sh" +if $IS_WSL; then echo "" - -if ! check_ros2_installed && [ ! -f "/opt/ros/${ROS_DISTRO}/setup.bash" ]; then - echo -e "${YELLOW}IMPORTANT:${NC}" - echo " ROS 2 installation may have failed. Please install manually:" - echo " See: https://docs.ros.org/en/${ROS_DISTRO}/Installation.html" - echo "" +echo " # Or with software rendering for WSL:" +echo " bash scripts/run_simulation.sh --software-render" fi +echo "" +echo -e "${GREEN}==========================================${NC}" diff --git a/worlds/empty_custom.world b/worlds/empty_custom.world index 20751dd..2fc7a46 100644 --- a/worlds/empty_custom.world +++ b/worlds/empty_custom.world @@ -15,6 +15,21 @@ model://ground_plane + + + model://iris_with_camera + uav + 0 0 0.1 0 0 0 + + + + + model://custom_ugv + ugv + 2 2 0.1 0 0 0 + + + true @@ -55,6 +70,7 @@ + true 0 0 0.01 0 0 0 @@ -74,6 +90,7 @@ + EARTH_WGS84 47.397742 diff --git a/worlds/iris_runway.world b/worlds/iris_runway.world new file mode 100644 index 0000000..d33d790 --- /dev/null +++ b/worlds/iris_runway.world @@ -0,0 +1,106 @@ + + + + + + + quick + 100 + 1.0 + + + 0.0 + 0.9 + 0.1 + 0.0 + + + 0.001 + 1.0 + 1000 + + + + model://sun + + + + model://ground_plane + + + + + + model://iris_with_ardupilot + + + + + + true + 10 0 0.01 0 0 0 + + + 1 1 0.02 + + 1 0 0 1 + 1 0 0 1 + + + + + + + true + 10 10 0.01 0 0 0 + + + 1 1 0.02 + + 0 1 0 1 + 0 1 0 1 + + + + + + + true + 0 10 0.01 0 0 0 + + + 1 1 0.02 + + 0 0 1 1 + 0 0 1 1 + + + + + + + true + 0 0 0.01 0 0 0 + + + + 0.50.02 + + + 1 1 0 1 + 1 1 0 1 + + + + + + + + EARTH_WGS84 + -35.363262 + 149.165237 + 584 + 0 + + +