Update Install Scripts
This commit is contained in:
300
README.md
300
README.md
@@ -1,7 +1,7 @@
|
|||||||
# UAV-UGV Gazebo SITL Simulation
|
# UAV-UGV Gazebo SITL Simulation
|
||||||
## GPS-Denied Navigation with Geofencing
|
## 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
|
## 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:
|
**GPS Usage**: GPS is ONLY used for:
|
||||||
- Geofencing (safety boundaries)
|
- Geofencing (safety boundaries)
|
||||||
- Initial position reference (optional)
|
|
||||||
- NOT used for waypoint navigation
|
- NOT used for waypoint navigation
|
||||||
- NOT used for position control
|
- NOT used for position control
|
||||||
|
|
||||||
This simulates real-world GPS-denied environments like:
|
## System Requirements
|
||||||
- Indoor spaces
|
|
||||||
- Urban canyons
|
- **Ubuntu 22.04 LTS** (or 24.04)
|
||||||
- GPS-jammed areas
|
- **16GB RAM** recommended (8GB minimum)
|
||||||
- Under bridges/tunnels
|
- **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
|
## Features
|
||||||
|
|
||||||
@@ -30,73 +93,10 @@ This simulates real-world GPS-denied environments like:
|
|||||||
- **Ground vehicle (UGV)** with vision sensors
|
- **Ground vehicle (UGV)** with vision sensors
|
||||||
- **Visual odometry** - camera-based position estimation
|
- **Visual odometry** - camera-based position estimation
|
||||||
- **Optical flow** - velocity estimation from downward camera
|
- **Optical flow** - velocity estimation from downward camera
|
||||||
- **Landmark navigation** - visual feature tracking
|
|
||||||
- **GPS geofencing** - safety boundaries only
|
- **GPS geofencing** - safety boundaries only
|
||||||
- **Single command launch** - everything runs from one script
|
- **ArduPilot SITL** - real flight controller firmware
|
||||||
- **NVIDIA GPU acceleration** support
|
- **MAVROS** - ROS 2 interface for MAVLink
|
||||||
- **Python virtual environment** for isolated dependencies
|
- **Multiple worlds** - indoor warehouse, urban canyon
|
||||||
- **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
|
|
||||||
```
|
|
||||||
|
|
||||||
## GPS-Denied Navigation Architecture
|
## GPS-Denied Navigation Architecture
|
||||||
|
|
||||||
@@ -121,103 +121,57 @@ bash scripts/run_simulation.sh --software-render
|
|||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
┌─────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────┐
|
||||||
│ Navigation Controller │
|
│ ArduPilot Flight Controller │
|
||||||
│ Commands: "Move 5m forward, 3m right" │
|
│ Receives position via MAVROS (external nav) │
|
||||||
│ (Relative coordinates only, NO GPS waypoints) │
|
│ 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
|
## Project Structure
|
||||||
|
|
||||||
- `launch/` - ROS 2 launch files
|
```
|
||||||
- `worlds/` - Gazebo world files (indoor, urban)
|
simulation/
|
||||||
- `models/` - Robot models (Iris with cameras, UGV)
|
├── setup.sh # One-command installation
|
||||||
- `src/vision/` - Visual odometry, optical flow
|
├── activate_venv.sh # Environment activation
|
||||||
- `src/localization/` - Position estimation, sensor fusion
|
├── scripts/
|
||||||
- `src/navigation/` - Path planning (relative coordinates)
|
│ ├── run_simulation.sh # Launch full simulation
|
||||||
- `src/safety/` - Geofencing (GPS-based)
|
│ └── kill_simulation.sh # Stop all processes
|
||||||
- `config/` - Configuration files
|
├── 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
|
## Documentation
|
||||||
|
|
||||||
- [Setup Guide](docs/setup_guide.md) - Linux installation
|
- [Setup Guide](docs/setup_guide.md) - Detailed installation
|
||||||
- [WSL Setup Guide](docs/wsl_setup_guide.md) - Windows WSL2 installation
|
- [WSL Setup Guide](docs/wsl_setup_guide.md) - Windows WSL2
|
||||||
- [Usage Guide](docs/usage.md)
|
- [Usage Guide](docs/usage.md) - How to use
|
||||||
- [Architecture Overview](docs/architecture.md)
|
- [Architecture](docs/architecture.md) - System design
|
||||||
- [GPS-Denied Navigation](docs/gps_denied_navigation.md)
|
- [GPS-Denied Navigation](docs/gps_denied_navigation.md) - Navigation approach
|
||||||
- [Troubleshooting](docs/troubleshooting.md)
|
- [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
|
## Key Differences from GPS Navigation
|
||||||
|
|
||||||
@@ -229,25 +183,3 @@ mission_waypoints = [
|
|||||||
| Indoor Capability | No | Yes |
|
| Indoor Capability | No | Yes |
|
||||||
| Drift | Minimal | Accumulates over time |
|
| Drift | Minimal | Accumulates over time |
|
||||||
| Geofencing | GPS-based | GPS-based (safety only) |
|
| 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).
|
|
||||||
|
|||||||
13
models/iris_with_ardupilot/model.config
Normal file
13
models/iris_with_ardupilot/model.config
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<model>
|
||||||
|
<name>Iris with ArduPilot</name>
|
||||||
|
<version>1.0</version>
|
||||||
|
<sdf version="1.6">model.sdf</sdf>
|
||||||
|
<author>
|
||||||
|
<name>UAV-UGV Simulation</name>
|
||||||
|
</author>
|
||||||
|
<description>
|
||||||
|
Iris quadcopter with ArduPilot SITL plugin for GPS-denied navigation testing.
|
||||||
|
Includes forward and downward cameras for visual odometry.
|
||||||
|
</description>
|
||||||
|
</model>
|
||||||
311
models/iris_with_ardupilot/model.sdf
Normal file
311
models/iris_with_ardupilot/model.sdf
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
<?xml version="1.0" ?>
|
||||||
|
<sdf version="1.6">
|
||||||
|
<model name="iris_with_ardupilot">
|
||||||
|
<pose>0 0 0.194923 0 0 0</pose>
|
||||||
|
|
||||||
|
<link name="base_link">
|
||||||
|
<inertial>
|
||||||
|
<pose>0 0 0 0 0 0</pose>
|
||||||
|
<mass>1.5</mass>
|
||||||
|
<inertia>
|
||||||
|
<ixx>0.029125</ixx>
|
||||||
|
<ixy>0</ixy>
|
||||||
|
<ixz>0</ixz>
|
||||||
|
<iyy>0.029125</iyy>
|
||||||
|
<iyz>0</iyz>
|
||||||
|
<izz>0.055225</izz>
|
||||||
|
</inertia>
|
||||||
|
</inertial>
|
||||||
|
|
||||||
|
<collision name="base_collision">
|
||||||
|
<pose>0 0 -0.08 0 0 0</pose>
|
||||||
|
<geometry>
|
||||||
|
<box><size>0.47 0.47 0.11</size></box>
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
|
||||||
|
<visual name="base_visual">
|
||||||
|
<pose>0 0 0 0 0 0</pose>
|
||||||
|
<geometry>
|
||||||
|
<mesh>
|
||||||
|
<uri>model://iris/meshes/iris.dae</uri>
|
||||||
|
<scale>1 1 1</scale>
|
||||||
|
</mesh>
|
||||||
|
</geometry>
|
||||||
|
</visual>
|
||||||
|
|
||||||
|
<!-- Fallback visual if mesh not found -->
|
||||||
|
<visual name="body_box">
|
||||||
|
<pose>0 0 0 0 0 0</pose>
|
||||||
|
<geometry>
|
||||||
|
<box><size>0.3 0.3 0.1</size></box>
|
||||||
|
</geometry>
|
||||||
|
<material>
|
||||||
|
<ambient>0.2 0.2 0.8 1</ambient>
|
||||||
|
<diffuse>0.2 0.2 0.8 1</diffuse>
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
|
||||||
|
<!-- IMU Sensor -->
|
||||||
|
<sensor name="imu_sensor" type="imu">
|
||||||
|
<always_on>true</always_on>
|
||||||
|
<update_rate>200</update_rate>
|
||||||
|
<imu>
|
||||||
|
<angular_velocity>
|
||||||
|
<x><noise type="gaussian"><mean>0</mean><stddev>0.0003</stddev></noise></x>
|
||||||
|
<y><noise type="gaussian"><mean>0</mean><stddev>0.0003</stddev></noise></y>
|
||||||
|
<z><noise type="gaussian"><mean>0</mean><stddev>0.0003</stddev></noise></z>
|
||||||
|
</angular_velocity>
|
||||||
|
<linear_acceleration>
|
||||||
|
<x><noise type="gaussian"><mean>0</mean><stddev>0.017</stddev></noise></x>
|
||||||
|
<y><noise type="gaussian"><mean>0</mean><stddev>0.017</stddev></noise></y>
|
||||||
|
<z><noise type="gaussian"><mean>0</mean><stddev>0.017</stddev></noise></z>
|
||||||
|
</linear_acceleration>
|
||||||
|
</imu>
|
||||||
|
</sensor>
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<!-- Rotor 0 (Front Right CW) -->
|
||||||
|
<link name="rotor_0">
|
||||||
|
<pose>0.13 -0.22 0.023 0 0 0</pose>
|
||||||
|
<inertial>
|
||||||
|
<mass>0.025</mass>
|
||||||
|
<inertia>
|
||||||
|
<ixx>9.75e-06</ixx><ixy>0</ixy><ixz>0</ixz>
|
||||||
|
<iyy>0.000166704</iyy><iyz>0</iyz><izz>0.000167604</izz>
|
||||||
|
</inertia>
|
||||||
|
</inertial>
|
||||||
|
<visual name="visual">
|
||||||
|
<geometry><cylinder><radius>0.1</radius><length>0.01</length></cylinder></geometry>
|
||||||
|
<material><ambient>0.1 0.1 0.1 1</ambient></material>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
<joint name="rotor_0_joint" type="revolute">
|
||||||
|
<parent>base_link</parent>
|
||||||
|
<child>rotor_0</child>
|
||||||
|
<axis>
|
||||||
|
<xyz>0 0 1</xyz>
|
||||||
|
<limit><lower>-1e16</lower><upper>1e16</upper></limit>
|
||||||
|
</axis>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<!-- Rotor 1 (Back Left CW) -->
|
||||||
|
<link name="rotor_1">
|
||||||
|
<pose>-0.13 0.22 0.023 0 0 0</pose>
|
||||||
|
<inertial>
|
||||||
|
<mass>0.025</mass>
|
||||||
|
<inertia>
|
||||||
|
<ixx>9.75e-06</ixx><ixy>0</ixy><ixz>0</ixz>
|
||||||
|
<iyy>0.000166704</iyy><iyz>0</iyz><izz>0.000167604</izz>
|
||||||
|
</inertia>
|
||||||
|
</inertial>
|
||||||
|
<visual name="visual">
|
||||||
|
<geometry><cylinder><radius>0.1</radius><length>0.01</length></cylinder></geometry>
|
||||||
|
<material><ambient>0.1 0.1 0.1 1</ambient></material>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
<joint name="rotor_1_joint" type="revolute">
|
||||||
|
<parent>base_link</parent>
|
||||||
|
<child>rotor_1</child>
|
||||||
|
<axis>
|
||||||
|
<xyz>0 0 1</xyz>
|
||||||
|
<limit><lower>-1e16</lower><upper>1e16</upper></limit>
|
||||||
|
</axis>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<!-- Rotor 2 (Front Left CCW) -->
|
||||||
|
<link name="rotor_2">
|
||||||
|
<pose>0.13 0.22 0.023 0 0 0</pose>
|
||||||
|
<inertial>
|
||||||
|
<mass>0.025</mass>
|
||||||
|
<inertia>
|
||||||
|
<ixx>9.75e-06</ixx><ixy>0</ixy><ixz>0</ixz>
|
||||||
|
<iyy>0.000166704</iyy><iyz>0</iyz><izz>0.000167604</izz>
|
||||||
|
</inertia>
|
||||||
|
</inertial>
|
||||||
|
<visual name="visual">
|
||||||
|
<geometry><cylinder><radius>0.1</radius><length>0.01</length></cylinder></geometry>
|
||||||
|
<material><ambient>0.1 0.1 0.1 1</ambient></material>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
<joint name="rotor_2_joint" type="revolute">
|
||||||
|
<parent>base_link</parent>
|
||||||
|
<child>rotor_2</child>
|
||||||
|
<axis>
|
||||||
|
<xyz>0 0 1</xyz>
|
||||||
|
<limit><lower>-1e16</lower><upper>1e16</upper></limit>
|
||||||
|
</axis>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<!-- Rotor 3 (Back Right CCW) -->
|
||||||
|
<link name="rotor_3">
|
||||||
|
<pose>-0.13 -0.22 0.023 0 0 0</pose>
|
||||||
|
<inertial>
|
||||||
|
<mass>0.025</mass>
|
||||||
|
<inertia>
|
||||||
|
<ixx>9.75e-06</ixx><ixy>0</ixy><ixz>0</ixz>
|
||||||
|
<iyy>0.000166704</iyy><iyz>0</iyz><izz>0.000167604</izz>
|
||||||
|
</inertia>
|
||||||
|
</inertial>
|
||||||
|
<visual name="visual">
|
||||||
|
<geometry><cylinder><radius>0.1</radius><length>0.01</length></cylinder></geometry>
|
||||||
|
<material><ambient>0.1 0.1 0.1 1</ambient></material>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
<joint name="rotor_3_joint" type="revolute">
|
||||||
|
<parent>base_link</parent>
|
||||||
|
<child>rotor_3</child>
|
||||||
|
<axis>
|
||||||
|
<xyz>0 0 1</xyz>
|
||||||
|
<limit><lower>-1e16</lower><upper>1e16</upper></limit>
|
||||||
|
</axis>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<!-- Forward Camera for Visual Odometry -->
|
||||||
|
<link name="forward_camera_link">
|
||||||
|
<pose>0.1 0 0 0 0 0</pose>
|
||||||
|
<inertial>
|
||||||
|
<mass>0.01</mass>
|
||||||
|
<inertia>
|
||||||
|
<ixx>1e-5</ixx><ixy>0</ixy><ixz>0</ixz>
|
||||||
|
<iyy>1e-5</iyy><iyz>0</iyz><izz>1e-5</izz>
|
||||||
|
</inertia>
|
||||||
|
</inertial>
|
||||||
|
<visual name="visual">
|
||||||
|
<geometry><box><size>0.02 0.02 0.02</size></box></geometry>
|
||||||
|
<material><ambient>0 0 0 1</ambient></material>
|
||||||
|
</visual>
|
||||||
|
<sensor name="forward_camera" type="camera">
|
||||||
|
<camera>
|
||||||
|
<horizontal_fov>1.57</horizontal_fov>
|
||||||
|
<image>
|
||||||
|
<width>640</width>
|
||||||
|
<height>480</height>
|
||||||
|
<format>R8G8B8</format>
|
||||||
|
</image>
|
||||||
|
<clip><near>0.1</near><far>100</far></clip>
|
||||||
|
</camera>
|
||||||
|
<always_on>1</always_on>
|
||||||
|
<update_rate>30</update_rate>
|
||||||
|
<visualize>true</visualize>
|
||||||
|
<plugin name="camera_controller" filename="libgazebo_ros_camera.so">
|
||||||
|
<ros>
|
||||||
|
<namespace>/uav</namespace>
|
||||||
|
<remapping>image_raw:=camera/forward/image_raw</remapping>
|
||||||
|
<remapping>camera_info:=camera/forward/camera_info</remapping>
|
||||||
|
</ros>
|
||||||
|
<camera_name>forward_camera</camera_name>
|
||||||
|
<frame_name>forward_camera_link</frame_name>
|
||||||
|
</plugin>
|
||||||
|
</sensor>
|
||||||
|
</link>
|
||||||
|
<joint name="forward_camera_joint" type="fixed">
|
||||||
|
<parent>base_link</parent>
|
||||||
|
<child>forward_camera_link</child>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<!-- Downward Camera for Optical Flow -->
|
||||||
|
<link name="downward_camera_link">
|
||||||
|
<pose>0 0 -0.05 0 1.5708 0</pose>
|
||||||
|
<inertial>
|
||||||
|
<mass>0.01</mass>
|
||||||
|
<inertia>
|
||||||
|
<ixx>1e-5</ixx><ixy>0</ixy><ixz>0</ixz>
|
||||||
|
<iyy>1e-5</iyy><iyz>0</iyz><izz>1e-5</izz>
|
||||||
|
</inertia>
|
||||||
|
</inertial>
|
||||||
|
<sensor name="downward_camera" type="camera">
|
||||||
|
<camera>
|
||||||
|
<horizontal_fov>1.2</horizontal_fov>
|
||||||
|
<image>
|
||||||
|
<width>320</width>
|
||||||
|
<height>240</height>
|
||||||
|
<format>R8G8B8</format>
|
||||||
|
</image>
|
||||||
|
<clip><near>0.1</near><far>50</far></clip>
|
||||||
|
</camera>
|
||||||
|
<always_on>1</always_on>
|
||||||
|
<update_rate>60</update_rate>
|
||||||
|
<visualize>false</visualize>
|
||||||
|
<plugin name="camera_controller" filename="libgazebo_ros_camera.so">
|
||||||
|
<ros>
|
||||||
|
<namespace>/uav</namespace>
|
||||||
|
<remapping>image_raw:=camera/downward/image_raw</remapping>
|
||||||
|
<remapping>camera_info:=camera/downward/camera_info</remapping>
|
||||||
|
</ros>
|
||||||
|
<camera_name>downward_camera</camera_name>
|
||||||
|
<frame_name>downward_camera_link</frame_name>
|
||||||
|
</plugin>
|
||||||
|
</sensor>
|
||||||
|
</link>
|
||||||
|
<joint name="downward_camera_joint" type="fixed">
|
||||||
|
<parent>base_link</parent>
|
||||||
|
<child>downward_camera_link</child>
|
||||||
|
</joint>
|
||||||
|
|
||||||
|
<!-- ArduPilot Plugin -->
|
||||||
|
<plugin name="ardupilot_plugin" filename="libArduPilotPlugin.so">
|
||||||
|
<fdm_addr>127.0.0.1</fdm_addr>
|
||||||
|
<fdm_port_in>9002</fdm_port_in>
|
||||||
|
<fdm_port_out>9003</fdm_port_out>
|
||||||
|
<modelXYZToAirplaneXForwardZDown>0 0 0 3.141593 0 0</modelXYZToAirplaneXForwardZDown>
|
||||||
|
<gazeboXYZToNED>0 0 0 3.141593 0 0</gazeboXYZToNED>
|
||||||
|
<imuName>iris_with_ardupilot::base_link::imu_sensor</imuName>
|
||||||
|
<connectionTimeoutMaxCount>5</connectionTimeoutMaxCount>
|
||||||
|
|
||||||
|
<!-- Motor configuration -->
|
||||||
|
<control channel="0">
|
||||||
|
<jointName>rotor_0_joint</jointName>
|
||||||
|
<type>VELOCITY</type>
|
||||||
|
<offset>0</offset>
|
||||||
|
<p_gain>0.20</p_gain>
|
||||||
|
<i_gain>0</i_gain>
|
||||||
|
<d_gain>0</d_gain>
|
||||||
|
<i_max>0</i_max>
|
||||||
|
<i_min>0</i_min>
|
||||||
|
<cmd_max>2.5</cmd_max>
|
||||||
|
<cmd_min>-2.5</cmd_min>
|
||||||
|
<multiplier>838</multiplier>
|
||||||
|
</control>
|
||||||
|
<control channel="1">
|
||||||
|
<jointName>rotor_1_joint</jointName>
|
||||||
|
<type>VELOCITY</type>
|
||||||
|
<offset>0</offset>
|
||||||
|
<p_gain>0.20</p_gain>
|
||||||
|
<i_gain>0</i_gain>
|
||||||
|
<d_gain>0</d_gain>
|
||||||
|
<i_max>0</i_max>
|
||||||
|
<i_min>0</i_min>
|
||||||
|
<cmd_max>2.5</cmd_max>
|
||||||
|
<cmd_min>-2.5</cmd_min>
|
||||||
|
<multiplier>838</multiplier>
|
||||||
|
</control>
|
||||||
|
<control channel="2">
|
||||||
|
<jointName>rotor_2_joint</jointName>
|
||||||
|
<type>VELOCITY</type>
|
||||||
|
<offset>0</offset>
|
||||||
|
<p_gain>0.20</p_gain>
|
||||||
|
<i_gain>0</i_gain>
|
||||||
|
<d_gain>0</d_gain>
|
||||||
|
<i_max>0</i_max>
|
||||||
|
<i_min>0</i_min>
|
||||||
|
<cmd_max>2.5</cmd_max>
|
||||||
|
<cmd_min>-2.5</cmd_min>
|
||||||
|
<multiplier>-838</multiplier>
|
||||||
|
</control>
|
||||||
|
<control channel="3">
|
||||||
|
<jointName>rotor_3_joint</jointName>
|
||||||
|
<type>VELOCITY</type>
|
||||||
|
<offset>0</offset>
|
||||||
|
<p_gain>0.20</p_gain>
|
||||||
|
<i_gain>0</i_gain>
|
||||||
|
<d_gain>0</d_gain>
|
||||||
|
<i_max>0</i_max>
|
||||||
|
<i_min>0</i_min>
|
||||||
|
<cmd_max>2.5</cmd_max>
|
||||||
|
<cmd_min>-2.5</cmd_min>
|
||||||
|
<multiplier>-838</multiplier>
|
||||||
|
</control>
|
||||||
|
</plugin>
|
||||||
|
</model>
|
||||||
|
</sdf>
|
||||||
@@ -1,24 +1,90 @@
|
|||||||
<?xml version="1.0" ?>
|
<?xml version="1.0" ?>
|
||||||
<sdf version="1.6">
|
<sdf version="1.6">
|
||||||
|
<!-- Simple quadcopter model for testing without ArduPilot -->
|
||||||
<model name="iris_with_camera">
|
<model name="iris_with_camera">
|
||||||
<include>
|
<pose>0 0 0.1 0 0 0</pose>
|
||||||
<uri>model://iris</uri>
|
|
||||||
</include>
|
|
||||||
|
|
||||||
<link name="forward_camera_link">
|
<!-- Base/Body -->
|
||||||
<pose>0.1 0 0 0 0 0</pose>
|
<link name="base_link">
|
||||||
<inertial>
|
<inertial>
|
||||||
<mass>0.01</mass>
|
<mass>1.5</mass>
|
||||||
<inertia>
|
<inertia>
|
||||||
<ixx>0.00001</ixx><ixy>0</ixy><ixz>0</ixz>
|
<ixx>0.029125</ixx><ixy>0</ixy><ixz>0</ixz>
|
||||||
<iyy>0.00001</iyy><iyz>0</iyz><izz>0.00001</izz>
|
<iyy>0.029125</iyy><iyz>0</iyz><izz>0.055225</izz>
|
||||||
</inertia>
|
</inertia>
|
||||||
</inertial>
|
</inertial>
|
||||||
<visual name="visual">
|
|
||||||
<geometry><box><size>0.02 0.02 0.02</size></box></geometry>
|
<!-- Main body -->
|
||||||
|
<visual name="body_visual">
|
||||||
|
<geometry>
|
||||||
|
<box><size>0.3 0.3 0.1</size></box>
|
||||||
|
</geometry>
|
||||||
|
<material>
|
||||||
|
<ambient>0.2 0.2 0.8 1</ambient>
|
||||||
|
<diffuse>0.2 0.2 0.8 1</diffuse>
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
|
||||||
|
<collision name="body_collision">
|
||||||
|
<geometry>
|
||||||
|
<box><size>0.3 0.3 0.1</size></box>
|
||||||
|
</geometry>
|
||||||
|
</collision>
|
||||||
|
|
||||||
|
<!-- Arms -->
|
||||||
|
<visual name="arm1_visual">
|
||||||
|
<pose>0.15 0.15 0 0 0 0.785</pose>
|
||||||
|
<geometry><box><size>0.3 0.02 0.02</size></box></geometry>
|
||||||
|
<material><ambient>0.3 0.3 0.3 1</ambient></material>
|
||||||
|
</visual>
|
||||||
|
<visual name="arm2_visual">
|
||||||
|
<pose>-0.15 0.15 0 0 0 -0.785</pose>
|
||||||
|
<geometry><box><size>0.3 0.02 0.02</size></box></geometry>
|
||||||
|
<material><ambient>0.3 0.3 0.3 1</ambient></material>
|
||||||
|
</visual>
|
||||||
|
<visual name="arm3_visual">
|
||||||
|
<pose>-0.15 -0.15 0 0 0 0.785</pose>
|
||||||
|
<geometry><box><size>0.3 0.02 0.02</size></box></geometry>
|
||||||
|
<material><ambient>0.3 0.3 0.3 1</ambient></material>
|
||||||
|
</visual>
|
||||||
|
<visual name="arm4_visual">
|
||||||
|
<pose>0.15 -0.15 0 0 0 -0.785</pose>
|
||||||
|
<geometry><box><size>0.3 0.02 0.02</size></box></geometry>
|
||||||
|
<material><ambient>0.3 0.3 0.3 1</ambient></material>
|
||||||
|
</visual>
|
||||||
|
|
||||||
|
<!-- Rotors -->
|
||||||
|
<visual name="rotor1">
|
||||||
|
<pose>0.22 0.22 0.05 0 0 0</pose>
|
||||||
|
<geometry><cylinder><radius>0.1</radius><length>0.01</length></cylinder></geometry>
|
||||||
|
<material><ambient>0.1 0.1 0.1 1</ambient></material>
|
||||||
|
</visual>
|
||||||
|
<visual name="rotor2">
|
||||||
|
<pose>-0.22 0.22 0.05 0 0 0</pose>
|
||||||
|
<geometry><cylinder><radius>0.1</radius><length>0.01</length></cylinder></geometry>
|
||||||
|
<material><ambient>0.1 0.1 0.1 1</ambient></material>
|
||||||
|
</visual>
|
||||||
|
<visual name="rotor3">
|
||||||
|
<pose>-0.22 -0.22 0.05 0 0 0</pose>
|
||||||
|
<geometry><cylinder><radius>0.1</radius><length>0.01</length></cylinder></geometry>
|
||||||
|
<material><ambient>0.1 0.1 0.1 1</ambient></material>
|
||||||
|
</visual>
|
||||||
|
<visual name="rotor4">
|
||||||
|
<pose>0.22 -0.22 0.05 0 0 0</pose>
|
||||||
|
<geometry><cylinder><radius>0.1</radius><length>0.01</length></cylinder></geometry>
|
||||||
|
<material><ambient>0.1 0.1 0.1 1</ambient></material>
|
||||||
|
</visual>
|
||||||
|
|
||||||
|
<!-- Forward camera (small black box) -->
|
||||||
|
<visual name="forward_camera_visual">
|
||||||
|
<pose>0.18 0 0 0 0 0</pose>
|
||||||
|
<geometry><box><size>0.03 0.03 0.03</size></box></geometry>
|
||||||
<material><ambient>0 0 0 1</ambient></material>
|
<material><ambient>0 0 0 1</ambient></material>
|
||||||
</visual>
|
</visual>
|
||||||
|
|
||||||
|
<!-- Forward Camera Sensor -->
|
||||||
<sensor name="forward_camera" type="camera">
|
<sensor name="forward_camera" type="camera">
|
||||||
|
<pose>0.18 0 0 0 0 0</pose>
|
||||||
<camera>
|
<camera>
|
||||||
<horizontal_fov>1.57</horizontal_fov>
|
<horizontal_fov>1.57</horizontal_fov>
|
||||||
<image>
|
<image>
|
||||||
@@ -31,37 +97,11 @@
|
|||||||
<always_on>1</always_on>
|
<always_on>1</always_on>
|
||||||
<update_rate>30</update_rate>
|
<update_rate>30</update_rate>
|
||||||
<visualize>true</visualize>
|
<visualize>true</visualize>
|
||||||
<plugin name="camera_controller" filename="libgazebo_ros_camera.so">
|
|
||||||
<ros>
|
|
||||||
<namespace>/uav</namespace>
|
|
||||||
<remapping>image_raw:=camera/forward/image_raw</remapping>
|
|
||||||
<remapping>camera_info:=camera/forward/camera_info</remapping>
|
|
||||||
</ros>
|
|
||||||
<camera_name>forward_camera</camera_name>
|
|
||||||
<frame_name>forward_camera_link</frame_name>
|
|
||||||
</plugin>
|
|
||||||
</sensor>
|
</sensor>
|
||||||
</link>
|
|
||||||
|
<!-- Downward Camera Sensor -->
|
||||||
<joint name="forward_camera_joint" type="fixed">
|
|
||||||
<parent>iris::base_link</parent>
|
|
||||||
<child>forward_camera_link</child>
|
|
||||||
</joint>
|
|
||||||
|
|
||||||
<link name="downward_camera_link">
|
|
||||||
<pose>0 0 -0.05 0 1.5708 0</pose>
|
|
||||||
<inertial>
|
|
||||||
<mass>0.01</mass>
|
|
||||||
<inertia>
|
|
||||||
<ixx>0.00001</ixx><ixy>0</ixy><ixz>0</ixz>
|
|
||||||
<iyy>0.00001</iyy><iyz>0</iyz><izz>0.00001</izz>
|
|
||||||
</inertia>
|
|
||||||
</inertial>
|
|
||||||
<visual name="visual">
|
|
||||||
<geometry><box><size>0.02 0.02 0.02</size></box></geometry>
|
|
||||||
<material><ambient>0.3 0.3 0.3 1</ambient></material>
|
|
||||||
</visual>
|
|
||||||
<sensor name="downward_camera" type="camera">
|
<sensor name="downward_camera" type="camera">
|
||||||
|
<pose>0 0 -0.06 0 1.5708 0</pose>
|
||||||
<camera>
|
<camera>
|
||||||
<horizontal_fov>1.2</horizontal_fov>
|
<horizontal_fov>1.2</horizontal_fov>
|
||||||
<image>
|
<image>
|
||||||
@@ -74,55 +114,7 @@
|
|||||||
<always_on>1</always_on>
|
<always_on>1</always_on>
|
||||||
<update_rate>30</update_rate>
|
<update_rate>30</update_rate>
|
||||||
<visualize>false</visualize>
|
<visualize>false</visualize>
|
||||||
<plugin name="camera_controller" filename="libgazebo_ros_camera.so">
|
|
||||||
<ros>
|
|
||||||
<namespace>/uav</namespace>
|
|
||||||
<remapping>image_raw:=camera/downward/image_raw</remapping>
|
|
||||||
<remapping>camera_info:=camera/downward/camera_info</remapping>
|
|
||||||
</ros>
|
|
||||||
<camera_name>downward_camera</camera_name>
|
|
||||||
<frame_name>downward_camera_link</frame_name>
|
|
||||||
</plugin>
|
|
||||||
</sensor>
|
</sensor>
|
||||||
</link>
|
</link>
|
||||||
|
|
||||||
<joint name="downward_camera_joint" type="fixed">
|
|
||||||
<parent>iris::base_link</parent>
|
|
||||||
<child>downward_camera_link</child>
|
|
||||||
</joint>
|
|
||||||
|
|
||||||
<link name="rangefinder_link">
|
|
||||||
<pose>0 0 -0.06 0 1.5708 0</pose>
|
|
||||||
<inertial>
|
|
||||||
<mass>0.005</mass>
|
|
||||||
<inertia>
|
|
||||||
<ixx>0.000001</ixx><ixy>0</ixy><ixz>0</ixz>
|
|
||||||
<iyy>0.000001</iyy><iyz>0</iyz><izz>0.000001</izz>
|
|
||||||
</inertia>
|
|
||||||
</inertial>
|
|
||||||
<sensor name="rangefinder" type="ray">
|
|
||||||
<ray>
|
|
||||||
<scan>
|
|
||||||
<horizontal><samples>1</samples><resolution>1</resolution><min_angle>0</min_angle><max_angle>0</max_angle></horizontal>
|
|
||||||
</scan>
|
|
||||||
<range><min>0.1</min><max>10</max><resolution>0.01</resolution></range>
|
|
||||||
</ray>
|
|
||||||
<always_on>1</always_on>
|
|
||||||
<update_rate>30</update_rate>
|
|
||||||
<plugin name="range_plugin" filename="libgazebo_ros_ray_sensor.so">
|
|
||||||
<ros>
|
|
||||||
<namespace>/uav</namespace>
|
|
||||||
<remapping>~/out:=rangefinder/range</remapping>
|
|
||||||
</ros>
|
|
||||||
<output_type>sensor_msgs/Range</output_type>
|
|
||||||
<frame_name>rangefinder_link</frame_name>
|
|
||||||
</plugin>
|
|
||||||
</sensor>
|
|
||||||
</link>
|
|
||||||
|
|
||||||
<joint name="rangefinder_joint" type="fixed">
|
|
||||||
<parent>iris::base_link</parent>
|
|
||||||
<child>rangefinder_link</child>
|
|
||||||
</joint>
|
|
||||||
</model>
|
</model>
|
||||||
</sdf>
|
</sdf>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# Full simulation launch script with ArduPilot SITL
|
||||||
|
# This script launches Gazebo, ArduPilot SITL, and MAVROS
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Colors
|
|
||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
GREEN='\033[0;32m'
|
GREEN='\033[0;32m'
|
||||||
YELLOW='\033[1;33m'
|
YELLOW='\033[1;33m'
|
||||||
@@ -35,16 +37,26 @@ done
|
|||||||
|
|
||||||
if [ -z "$ROS_DISTRO" ]; then
|
if [ -z "$ROS_DISTRO" ]; then
|
||||||
echo -e "${RED}ERROR: No ROS 2 installation found!${NC}"
|
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
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "${GREEN}Using ROS 2: $ROS_DISTRO${NC}"
|
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 /opt/ros/${ROS_DISTRO}/setup.bash
|
||||||
|
|
||||||
# Source Gazebo setup (CRITICAL for shader paths)
|
|
||||||
if [ -f /usr/share/gazebo/setup.bash ]; then
|
if [ -f /usr/share/gazebo/setup.bash ]; then
|
||||||
source /usr/share/gazebo/setup.bash
|
source /usr/share/gazebo/setup.bash
|
||||||
elif [ -f /usr/share/gazebo-11/setup.bash ]; then
|
elif [ -f /usr/share/gazebo-11/setup.bash ]; then
|
||||||
@@ -52,9 +64,10 @@ elif [ -f /usr/share/gazebo-11/setup.bash ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Parse arguments
|
# Parse arguments
|
||||||
WORLD=""
|
WORLD="$PROJECT_DIR/worlds/iris_runway.world"
|
||||||
|
VEHICLE="copter"
|
||||||
USE_SOFTWARE_RENDER=false
|
USE_SOFTWARE_RENDER=false
|
||||||
HEADLESS=false
|
INSTANCE=0
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
case $1 in
|
case $1 in
|
||||||
@@ -62,34 +75,32 @@ while [[ $# -gt 0 ]]; do
|
|||||||
WORLD="$2"
|
WORLD="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
--headless)
|
--vehicle)
|
||||||
HEADLESS=true
|
VEHICLE="$2"
|
||||||
shift
|
shift 2
|
||||||
;;
|
;;
|
||||||
--no-gpu|--software-render)
|
--software-render)
|
||||||
USE_SOFTWARE_RENDER=true
|
USE_SOFTWARE_RENDER=true
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
--instance)
|
||||||
|
INSTANCE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
--help)
|
--help)
|
||||||
echo "Usage: $0 [OPTIONS] [WORLD_FILE]"
|
echo "Usage: $0 [OPTIONS]"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Options:"
|
echo "Options:"
|
||||||
echo " --world FILE Specify world file (default: empty_custom.world)"
|
echo " --world FILE World file (default: iris_runway.world)"
|
||||||
echo " --headless Run without GUI (gzserver only)"
|
echo " --vehicle TYPE Vehicle type: copter, rover (default: copter)"
|
||||||
echo " --software-render Force software rendering (recommended for WSL)"
|
echo " --software-render Force software rendering (for WSL)"
|
||||||
echo " --help Show this help"
|
echo " --instance N Vehicle instance number (default: 0)"
|
||||||
echo ""
|
echo " --help Show this help"
|
||||||
echo "Examples:"
|
|
||||||
echo " $0 # Default world"
|
|
||||||
echo " $0 worlds/indoor_warehouse.world # Indoor environment"
|
|
||||||
echo " $0 --software-render # For WSL without GPU"
|
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
if [ -f "$1" ]; then
|
if [ -f "$1" ]; then
|
||||||
WORLD="$1"
|
WORLD="$1"
|
||||||
elif [ -f "$PROJECT_DIR/$1" ]; then
|
|
||||||
WORLD="$PROJECT_DIR/$1"
|
|
||||||
elif [ -f "$PROJECT_DIR/worlds/$1" ]; then
|
elif [ -f "$PROJECT_DIR/worlds/$1" ]; then
|
||||||
WORLD="$PROJECT_DIR/worlds/$1"
|
WORLD="$PROJECT_DIR/worlds/$1"
|
||||||
fi
|
fi
|
||||||
@@ -98,109 +109,172 @@ while [[ $# -gt 0 ]]; do
|
|||||||
esac
|
esac
|
||||||
done
|
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
|
# Setup Gazebo paths
|
||||||
export GAZEBO_MODEL_PATH="$PROJECT_DIR/models:${GAZEBO_MODEL_PATH:-}"
|
export GAZEBO_MODEL_PATH="$PROJECT_DIR/models:${GAZEBO_MODEL_PATH:-}"
|
||||||
export GAZEBO_RESOURCE_PATH="$PROJECT_DIR/worlds:${GAZEBO_RESOURCE_PATH:-}"
|
export GAZEBO_RESOURCE_PATH="$PROJECT_DIR/worlds:${GAZEBO_RESOURCE_PATH:-}"
|
||||||
|
|
||||||
# ArduPilot Gazebo paths (if installed)
|
|
||||||
if [ -d "$HOME/ardupilot_gazebo" ]; then
|
if [ -d "$HOME/ardupilot_gazebo" ]; then
|
||||||
export GAZEBO_MODEL_PATH="$HOME/ardupilot_gazebo/models:$GAZEBO_MODEL_PATH"
|
export GAZEBO_MODEL_PATH="$HOME/ardupilot_gazebo/models:$GAZEBO_MODEL_PATH"
|
||||||
export GAZEBO_RESOURCE_PATH="$HOME/ardupilot_gazebo/worlds:$GAZEBO_RESOURCE_PATH"
|
export GAZEBO_RESOURCE_PATH="$HOME/ardupilot_gazebo/worlds:$GAZEBO_RESOURCE_PATH"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# WSL-specific setup
|
# WSL/Display setup
|
||||||
if $IS_WSL; then
|
if $IS_WSL; then
|
||||||
# Source WSL environment if exists
|
|
||||||
if [ -f "$PROJECT_DIR/wsl_env.sh" ]; then
|
if [ -f "$PROJECT_DIR/wsl_env.sh" ]; then
|
||||||
source "$PROJECT_DIR/wsl_env.sh"
|
source "$PROJECT_DIR/wsl_env.sh"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Set DISPLAY if not set
|
|
||||||
if [ -z "$DISPLAY" ]; then
|
if [ -z "$DISPLAY" ]; then
|
||||||
if [ -d "/mnt/wslg" ]; then
|
export DISPLAY=:0
|
||||||
export DISPLAY=:0
|
|
||||||
else
|
|
||||||
export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "${BLUE}DISPLAY: $DISPLAY${NC}"
|
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
|
fi
|
||||||
|
|
||||||
# Apply software rendering if requested or in WSL with issues
|
|
||||||
if $USE_SOFTWARE_RENDER; then
|
if $USE_SOFTWARE_RENDER; then
|
||||||
echo -e "${YELLOW}Using software rendering${NC}"
|
echo -e "${YELLOW}Using software rendering${NC}"
|
||||||
export LIBGL_ALWAYS_SOFTWARE=1
|
export LIBGL_ALWAYS_SOFTWARE=1
|
||||||
export MESA_GL_VERSION_OVERRIDE=3.3
|
export MESA_GL_VERSION_OVERRIDE=3.3
|
||||||
export MESA_GLSL_VERSION_OVERRIDE=330
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Cleanup function
|
# Cleanup function
|
||||||
cleanup() {
|
cleanup() {
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${YELLOW}Shutting down simulation...${NC}"
|
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 "gzserver" 2>/dev/null || true
|
||||||
pkill -f "gzclient" 2>/dev/null || true
|
pkill -f "gzclient" 2>/dev/null || true
|
||||||
pkill -f "gazebo" 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}"
|
echo -e "${GREEN}Cleanup complete.${NC}"
|
||||||
}
|
}
|
||||||
|
|
||||||
trap cleanup EXIT INT TERM
|
trap cleanup EXIT INT TERM
|
||||||
|
|
||||||
# Activate virtual environment if exists
|
# Activate virtual environment
|
||||||
if [ -f "$PROJECT_DIR/venv/bin/activate" ]; then
|
if [ -f "$PROJECT_DIR/venv/bin/activate" ]; then
|
||||||
source "$PROJECT_DIR/venv/bin/activate"
|
source "$PROJECT_DIR/venv/bin/activate"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Source workspace if built
|
# Use ardupilot_gazebo iris world if no custom world specified
|
||||||
if [ -f "$PROJECT_DIR/../install/setup.bash" ]; then
|
if [ ! -f "$WORLD" ]; then
|
||||||
source "$PROJECT_DIR/../install/setup.bash"
|
if [ -f "$HOME/ardupilot_gazebo/worlds/iris_arducopter_runway.world" ]; then
|
||||||
elif [ -f "$PROJECT_DIR/install/setup.bash" ]; then
|
WORLD="$HOME/ardupilot_gazebo/worlds/iris_arducopter_runway.world"
|
||||||
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"
|
|
||||||
else
|
else
|
||||||
gazebo --verbose "$WORLD"
|
echo -e "${RED}ERROR: World file not found: $WORLD${NC}"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
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
|
||||||
|
|||||||
@@ -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"
|
|
||||||
@@ -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 ""
|
|
||||||
552
setup.sh
552
setup.sh
@@ -1,17 +1,21 @@
|
|||||||
#!/bin/bash
|
#!/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
|
set -e
|
||||||
|
|
||||||
# Colors for output
|
|
||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
GREEN='\033[0;32m'
|
GREEN='\033[0;32m'
|
||||||
YELLOW='\033[1;33m'
|
YELLOW='\033[1;33m'
|
||||||
BLUE='\033[0;34m'
|
BLUE='\033[0;34m'
|
||||||
NC='\033[0m' # No Color
|
CYAN='\033[0;36m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
print_header() {
|
print_header() {
|
||||||
|
echo ""
|
||||||
echo -e "${BLUE}==========================================${NC}"
|
echo -e "${BLUE}==========================================${NC}"
|
||||||
echo -e "${BLUE} UAV-UGV Simulation Setup${NC}"
|
echo -e "${BLUE} $1${NC}"
|
||||||
echo -e "${BLUE} GPS-Denied Navigation with Geofencing${NC}"
|
|
||||||
echo -e "${BLUE}==========================================${NC}"
|
echo -e "${BLUE}==========================================${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
}
|
}
|
||||||
@@ -20,6 +24,10 @@ print_step() {
|
|||||||
echo -e "${GREEN}[$1/$TOTAL_STEPS] $2${NC}"
|
echo -e "${GREEN}[$1/$TOTAL_STEPS] $2${NC}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print_info() {
|
||||||
|
echo -e "${CYAN}INFO: $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
print_warning() {
|
print_warning() {
|
||||||
echo -e "${YELLOW}WARNING: $1${NC}"
|
echo -e "${YELLOW}WARNING: $1${NC}"
|
||||||
}
|
}
|
||||||
@@ -28,21 +36,14 @@ print_error() {
|
|||||||
echo -e "${RED}ERROR: $1${NC}"
|
echo -e "${RED}ERROR: $1${NC}"
|
||||||
}
|
}
|
||||||
|
|
||||||
print_info() {
|
|
||||||
echo -e "${BLUE}INFO: $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Detect environment
|
# Detect environment
|
||||||
detect_environment() {
|
detect_environment() {
|
||||||
IS_WSL=false
|
IS_WSL=false
|
||||||
IS_WSL2=false
|
IS_WSL2=false
|
||||||
UBUNTU_VERSION=""
|
|
||||||
ROS_DISTRO=""
|
|
||||||
|
|
||||||
# Detect WSL
|
|
||||||
if grep -qEi "(microsoft|wsl)" /proc/version 2>/dev/null; then
|
if grep -qEi "(microsoft|wsl)" /proc/version 2>/dev/null; then
|
||||||
IS_WSL=true
|
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
|
IS_WSL2=true
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -54,330 +55,319 @@ detect_environment() {
|
|||||||
UBUNTU_CODENAME="$VERSION_CODENAME"
|
UBUNTU_CODENAME="$VERSION_CODENAME"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Determine ROS distro based on Ubuntu version
|
# Determine ROS distro
|
||||||
case "$UBUNTU_VERSION" in
|
case "$UBUNTU_VERSION" in
|
||||||
"22.04")
|
"22.04") ROS_DISTRO="humble" ;;
|
||||||
ROS_DISTRO="humble"
|
"24.04") ROS_DISTRO="jazzy" ;;
|
||||||
;;
|
"20.04") ROS_DISTRO="galactic" ;;
|
||||||
"24.04")
|
*) ROS_DISTRO="humble" ;;
|
||||||
ROS_DISTRO="jazzy"
|
|
||||||
;;
|
|
||||||
"20.04")
|
|
||||||
ROS_DISTRO="galactic"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
ROS_DISTRO="humble" # Default fallback
|
|
||||||
;;
|
|
||||||
esac
|
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
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
check_ros2_installed() {
|
cd "$SCRIPT_DIR"
|
||||||
if [ -d "/opt/ros/$ROS_DISTRO" ]; then
|
|
||||||
return 0
|
print_header "UAV-UGV Simulation - Complete Setup"
|
||||||
else
|
echo "GPS-Denied Navigation with Geofencing"
|
||||||
return 1
|
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
|
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] \
|
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" | \
|
http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main" | \
|
||||||
sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
|
sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
|
||||||
|
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
}
|
sudo apt-get install -y ros-${ROS_DISTRO}-desktop python3-colcon-common-extensions
|
||||||
|
|
||||||
# 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
|
|
||||||
else
|
else
|
||||||
# WSL1
|
print_info "ROS 2 $ROS_DISTRO already installed"
|
||||||
export DISPLAY=localhost:0
|
|
||||||
fi
|
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++))
|
||||||
|
|
||||||
# Step: WSL-specific setup
|
# ============================================================================
|
||||||
if $IS_WSL; then
|
# STEP 4: Install ROS 2 Packages
|
||||||
print_step $STEP "Setting up WSL environment..."
|
# ============================================================================
|
||||||
setup_wsl
|
print_step $STEP "Installing ROS 2 packages"
|
||||||
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..."
|
|
||||||
sudo apt-get install -y \
|
sudo apt-get install -y \
|
||||||
python3-pip \
|
ros-${ROS_DISTRO}-mavros \
|
||||||
python3-venv \
|
ros-${ROS_DISTRO}-mavros-extras \
|
||||||
python3-opencv \
|
ros-${ROS_DISTRO}-cv-bridge \
|
||||||
libopencv-dev \
|
ros-${ROS_DISTRO}-image-transport \
|
||||||
python3-colcon-common-extensions \
|
ros-${ROS_DISTRO}-tf2 \
|
||||||
build-essential \
|
ros-${ROS_DISTRO}-tf2-ros \
|
||||||
cmake \
|
ros-${ROS_DISTRO}-tf2-geometry-msgs \
|
||||||
git || true
|
ros-${ROS_DISTRO}-gazebo-ros-pkgs 2>/dev/null || \
|
||||||
((STEP++))
|
print_warning "Some ROS packages not available for $ROS_DISTRO"
|
||||||
|
|
||||||
# Step: Install ROS 2 packages
|
# Install GeographicLib datasets for MAVROS
|
||||||
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..."
|
|
||||||
GEOGRAPHICLIB_SCRIPT="/opt/ros/${ROS_DISTRO}/lib/mavros/install_geographiclib_datasets.sh"
|
GEOGRAPHICLIB_SCRIPT="/opt/ros/${ROS_DISTRO}/lib/mavros/install_geographiclib_datasets.sh"
|
||||||
if [ -f "$GEOGRAPHICLIB_SCRIPT" ]; then
|
if [ -f "$GEOGRAPHICLIB_SCRIPT" ]; then
|
||||||
if [ ! -f /usr/share/GeographicLib/geoids/egm96-5.pgm ]; then
|
if [ ! -f /usr/share/GeographicLib/geoids/egm96-5.pgm ]; then
|
||||||
sudo "$GEOGRAPHICLIB_SCRIPT" || print_warning "GeographicLib datasets installation failed"
|
print_info "Installing GeographicLib datasets (this may take a minute)"
|
||||||
else
|
sudo "$GEOGRAPHICLIB_SCRIPT" || print_warning "GeographicLib installation failed"
|
||||||
print_info "GeographicLib datasets already installed"
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
print_warning "MAVROS not installed, skipping GeographicLib datasets"
|
|
||||||
fi
|
fi
|
||||||
((STEP++))
|
((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
|
if [ ! -d "venv" ]; then
|
||||||
python3 -m venv venv
|
python3 -m venv venv
|
||||||
fi
|
fi
|
||||||
|
|
||||||
source venv/bin/activate
|
source venv/bin/activate
|
||||||
|
|
||||||
# Upgrade pip and install dependencies
|
|
||||||
pip install --upgrade pip
|
pip install --upgrade pip
|
||||||
pip install -r requirements.txt || {
|
pip install -r requirements.txt || print_warning "Some Python packages failed"
|
||||||
print_warning "Some Python packages failed to install. Check requirements.txt"
|
deactivate
|
||||||
}
|
|
||||||
((STEP++))
|
((STEP++))
|
||||||
|
|
||||||
# Step: Build ROS 2 package
|
# ============================================================================
|
||||||
print_step $STEP "Building ROS 2 package..."
|
# STEP 9: Configure Environment
|
||||||
if [ -f "/opt/ros/${ROS_DISTRO}/setup.bash" ]; then
|
# ============================================================================
|
||||||
source /opt/ros/${ROS_DISTRO}/setup.bash
|
print_step $STEP "Configuring environment"
|
||||||
|
|
||||||
# Try to build if in a ROS workspace
|
# Create WSL environment file
|
||||||
if [ -d "$SCRIPT_DIR/../src" ] || [ -f "$SCRIPT_DIR/package.xml" ]; then
|
if $IS_WSL; then
|
||||||
cd "$SCRIPT_DIR/.."
|
cat > "$SCRIPT_DIR/wsl_env.sh" << 'WSLEOF'
|
||||||
colcon build --packages-select uav_ugv_simulation --symlink-install 2>/dev/null || {
|
#!/bin/bash
|
||||||
print_warning "Colcon build skipped. To build manually:"
|
# WSL Environment for UAV-UGV Simulation
|
||||||
print_info " cd ~/ros2_ws && colcon build --packages-select uav_ugv_simulation"
|
|
||||||
}
|
if [ -d "/mnt/wslg" ]; then
|
||||||
cd "$SCRIPT_DIR"
|
export DISPLAY=:0
|
||||||
fi
|
|
||||||
else
|
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
|
fi
|
||||||
((STEP++))
|
|
||||||
|
|
||||||
# Step: Make scripts executable and create activation script
|
export LIBGL_ALWAYS_INDIRECT=0
|
||||||
print_step $STEP "Finalizing setup..."
|
export MESA_GL_VERSION_OVERRIDE=3.3
|
||||||
chmod +x scripts/*.sh 2>/dev/null || true
|
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
|
# Create activation script
|
||||||
cat > activate_venv.sh << EOF
|
cat > "$SCRIPT_DIR/activate_venv.sh" << EOF
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
SCRIPT_DIR="\$(cd "\$(dirname "\${BASH_SOURCE[0]}")" && pwd)"
|
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 "\$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
|
# Gazebo paths
|
||||||
export GAZEBO_MODEL_PATH="\$SCRIPT_DIR/models:\$GAZEBO_MODEL_PATH"
|
export GAZEBO_MODEL_PATH="\$SCRIPT_DIR/models:\$HOME/ardupilot_gazebo/models:\${GAZEBO_MODEL_PATH:-}"
|
||||||
export GAZEBO_RESOURCE_PATH="\$SCRIPT_DIR/worlds:\$GAZEBO_RESOURCE_PATH"
|
export GAZEBO_RESOURCE_PATH="\$SCRIPT_DIR/worlds:\$HOME/ardupilot_gazebo/worlds:\${GAZEBO_RESOURCE_PATH:-}"
|
||||||
|
|
||||||
# ArduPilot Gazebo (if installed)
|
# ArduPilot
|
||||||
if [ -d "\$HOME/ardupilot_gazebo" ]; then
|
export PATH="\$PATH:\$HOME/ardupilot/Tools/autotest"
|
||||||
export GAZEBO_MODEL_PATH="\$HOME/ardupilot_gazebo/models:\$GAZEBO_MODEL_PATH"
|
export ARDUPILOT_HOME="\$HOME/ardupilot"
|
||||||
export GAZEBO_RESOURCE_PATH="\$HOME/ardupilot_gazebo/worlds:\$GAZEBO_RESOURCE_PATH"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# WSL environment (if applicable)
|
# WSL
|
||||||
if [ -f "\$SCRIPT_DIR/wsl_env.sh" ]; then
|
if grep -qEi "(microsoft|wsl)" /proc/version 2>/dev/null; then
|
||||||
source "\$SCRIPT_DIR/wsl_env.sh"
|
[ -f "\$SCRIPT_DIR/wsl_env.sh" ] && source "\$SCRIPT_DIR/wsl_env.sh"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "\033[0;32mEnvironment activated (ROS 2 ${ROS_DISTRO})\033[0m"
|
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 ""
|
||||||
echo -e "${GREEN}==========================================${NC}"
|
echo "Run simulation: bash scripts/run_simulation.sh"
|
||||||
echo -e "${GREEN} Setup Complete!${NC}"
|
echo "With rendering: bash scripts/run_simulation.sh --software-render"
|
||||||
echo -e "${GREEN}==========================================${NC}"
|
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 ""
|
echo ""
|
||||||
|
|
||||||
if $IS_WSL; then
|
if $IS_WSL; then
|
||||||
echo -e "${YELLOW}WSL Setup Notes:${NC}"
|
echo -e "${YELLOW}WSL Setup Notes:${NC}"
|
||||||
echo " - WSL environment file created: wsl_env.sh"
|
echo " - GUI apps require WSLg (Windows 11) or VcXsrv (Windows 10)"
|
||||||
echo " - For GUI apps, ensure X server is running (Windows 11 has WSLg built-in)"
|
echo " - Use --software-render flag if graphics are slow"
|
||||||
echo " - See docs/wsl_setup_guide.md for detailed instructions"
|
|
||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "${BLUE}Next steps:${NC}"
|
echo -e "${CYAN}To run the simulation:${NC}"
|
||||||
echo " 1. source ~/.bashrc"
|
|
||||||
echo " 2. source activate_venv.sh"
|
|
||||||
echo " 3. bash scripts/run_simulation.sh"
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BLUE}GPS-Denied Navigation:${NC}"
|
echo " cd $SCRIPT_DIR"
|
||||||
echo " - All navigation uses LOCAL coordinates"
|
echo " source activate_venv.sh"
|
||||||
echo " - GPS is ONLY used for geofencing"
|
echo " bash scripts/run_simulation.sh"
|
||||||
|
if $IS_WSL; then
|
||||||
echo ""
|
echo ""
|
||||||
|
echo " # Or with software rendering for WSL:"
|
||||||
if ! check_ros2_installed && [ ! -f "/opt/ros/${ROS_DISTRO}/setup.bash" ]; then
|
echo " bash scripts/run_simulation.sh --software-render"
|
||||||
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 ""
|
|
||||||
fi
|
fi
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}==========================================${NC}"
|
||||||
|
|||||||
@@ -15,6 +15,21 @@
|
|||||||
<uri>model://ground_plane</uri>
|
<uri>model://ground_plane</uri>
|
||||||
</include>
|
</include>
|
||||||
|
|
||||||
|
<!-- UAV - Iris Quadcopter with Cameras -->
|
||||||
|
<include>
|
||||||
|
<uri>model://iris_with_camera</uri>
|
||||||
|
<name>uav</name>
|
||||||
|
<pose>0 0 0.1 0 0 0</pose>
|
||||||
|
</include>
|
||||||
|
|
||||||
|
<!-- UGV - Ground Vehicle -->
|
||||||
|
<include>
|
||||||
|
<uri>model://custom_ugv</uri>
|
||||||
|
<name>ugv</name>
|
||||||
|
<pose>2 2 0.1 0 0 0</pose>
|
||||||
|
</include>
|
||||||
|
|
||||||
|
<!-- Visual Markers for GPS-Denied Navigation -->
|
||||||
<model name="visual_markers">
|
<model name="visual_markers">
|
||||||
<static>true</static>
|
<static>true</static>
|
||||||
<link name="marker_0">
|
<link name="marker_0">
|
||||||
@@ -55,6 +70,7 @@
|
|||||||
</link>
|
</link>
|
||||||
</model>
|
</model>
|
||||||
|
|
||||||
|
<!-- Origin Marker (Yellow) -->
|
||||||
<model name="origin_marker">
|
<model name="origin_marker">
|
||||||
<static>true</static>
|
<static>true</static>
|
||||||
<pose>0 0 0.01 0 0 0</pose>
|
<pose>0 0 0.01 0 0 0</pose>
|
||||||
@@ -74,6 +90,7 @@
|
|||||||
</link>
|
</link>
|
||||||
</model>
|
</model>
|
||||||
|
|
||||||
|
<!-- Spherical coordinates for geofencing reference -->
|
||||||
<spherical_coordinates>
|
<spherical_coordinates>
|
||||||
<surface_model>EARTH_WGS84</surface_model>
|
<surface_model>EARTH_WGS84</surface_model>
|
||||||
<latitude_deg>47.397742</latitude_deg>
|
<latitude_deg>47.397742</latitude_deg>
|
||||||
|
|||||||
106
worlds/iris_runway.world
Normal file
106
worlds/iris_runway.world
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
<?xml version="1.0" ?>
|
||||||
|
<sdf version="1.6">
|
||||||
|
<world name="iris_runway">
|
||||||
|
<physics type="ode">
|
||||||
|
<ode>
|
||||||
|
<solver>
|
||||||
|
<type>quick</type>
|
||||||
|
<iters>100</iters>
|
||||||
|
<sor>1.0</sor>
|
||||||
|
</solver>
|
||||||
|
<constraints>
|
||||||
|
<cfm>0.0</cfm>
|
||||||
|
<erp>0.9</erp>
|
||||||
|
<contact_max_correcting_vel>0.1</contact_max_correcting_vel>
|
||||||
|
<contact_surface_layer>0.0</contact_surface_layer>
|
||||||
|
</constraints>
|
||||||
|
</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>
|
||||||
|
|
||||||
|
<include>
|
||||||
|
<uri>model://sun</uri>
|
||||||
|
</include>
|
||||||
|
|
||||||
|
<include>
|
||||||
|
<uri>model://ground_plane</uri>
|
||||||
|
</include>
|
||||||
|
|
||||||
|
<!-- ArduPilot Iris Quadcopter -->
|
||||||
|
<model name="iris">
|
||||||
|
<include>
|
||||||
|
<uri>model://iris_with_ardupilot</uri>
|
||||||
|
</include>
|
||||||
|
</model>
|
||||||
|
|
||||||
|
<!-- Visual Navigation Markers -->
|
||||||
|
<model name="marker_red">
|
||||||
|
<static>true</static>
|
||||||
|
<pose>10 0 0.01 0 0 0</pose>
|
||||||
|
<link name="link">
|
||||||
|
<visual name="visual">
|
||||||
|
<geometry><box><size>1 1 0.02</size></box></geometry>
|
||||||
|
<material>
|
||||||
|
<ambient>1 0 0 1</ambient>
|
||||||
|
<diffuse>1 0 0 1</diffuse>
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
</model>
|
||||||
|
|
||||||
|
<model name="marker_green">
|
||||||
|
<static>true</static>
|
||||||
|
<pose>10 10 0.01 0 0 0</pose>
|
||||||
|
<link name="link">
|
||||||
|
<visual name="visual">
|
||||||
|
<geometry><box><size>1 1 0.02</size></box></geometry>
|
||||||
|
<material>
|
||||||
|
<ambient>0 1 0 1</ambient>
|
||||||
|
<diffuse>0 1 0 1</diffuse>
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
</model>
|
||||||
|
|
||||||
|
<model name="marker_blue">
|
||||||
|
<static>true</static>
|
||||||
|
<pose>0 10 0.01 0 0 0</pose>
|
||||||
|
<link name="link">
|
||||||
|
<visual name="visual">
|
||||||
|
<geometry><box><size>1 1 0.02</size></box></geometry>
|
||||||
|
<material>
|
||||||
|
<ambient>0 0 1 1</ambient>
|
||||||
|
<diffuse>0 0 1 1</diffuse>
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
</model>
|
||||||
|
|
||||||
|
<model name="origin_marker">
|
||||||
|
<static>true</static>
|
||||||
|
<pose>0 0 0.01 0 0 0</pose>
|
||||||
|
<link name="link">
|
||||||
|
<visual name="visual">
|
||||||
|
<geometry>
|
||||||
|
<cylinder><radius>0.5</radius><length>0.02</length></cylinder>
|
||||||
|
</geometry>
|
||||||
|
<material>
|
||||||
|
<ambient>1 1 0 1</ambient>
|
||||||
|
<diffuse>1 1 0 1</diffuse>
|
||||||
|
</material>
|
||||||
|
</visual>
|
||||||
|
</link>
|
||||||
|
</model>
|
||||||
|
|
||||||
|
<!-- Spherical coordinates for GPS geofencing -->
|
||||||
|
<spherical_coordinates>
|
||||||
|
<surface_model>EARTH_WGS84</surface_model>
|
||||||
|
<latitude_deg>-35.363262</latitude_deg>
|
||||||
|
<longitude_deg>149.165237</longitude_deg>
|
||||||
|
<elevation>584</elevation>
|
||||||
|
<heading_deg>0</heading_deg>
|
||||||
|
</spherical_coordinates>
|
||||||
|
</world>
|
||||||
|
</sdf>
|
||||||
Reference in New Issue
Block a user