---
name: matlab/matlab-create-uav-scenario
source: https://app.decimal.ai/s/matlab-matlab-create-uav-scenario@1/SKILL.md
source_sha256: 36485ee57407
---

# Create UAV Scenario

Build and simulate UAV scenarios with terrain, buildings, sensor-equipped platforms, and 3D visualization using the UAV Toolbox `uavScenario` framework.

## When to Use

- Creating a UAV simulation environment with real-world terrain or buildings
- Adding sensor-equipped UAV platforms (GPS, IMU, lidar) to a scenario
- Running a time-stepping simulation loop with sensor readings
- Visualizing UAV flight in 3D with `show3D`

## When NOT to Use

- Generating flight trajectories (waypoint design, min-snap) — use trajectory skill instead
- Simulink-based UAV simulation (UAV Toolbox Simulink blocks)
- Path planning and obstacle avoidance algorithms
- Coordinate conversion only (`ned2lla`, `lla2ned`) — use these directly

## Workflow

1. **Create scenario** — `uavScenario` with `ReferenceLocation` and `UpdateRate`
2. **Add terrain** — `addMesh(scene,"terrain",...)` with GMTED2010 or custom DTED
3. **Add buildings** — `addMesh(scene,"buildings",...)` from OSM file
4. **Add platform** — `uavPlatform` with trajectory, then `updateMesh`
5. **Attach sensors** — `uavSensor` adaptor binding sensor to platform
6. **Run simulation** — `setup` → `advance` → `updateSensors` → `read` loop
7. **Visualize** — `show3D` with `FastUpdate` for animation

## Key Functions

| Function | Purpose | Toolbox |
|----------|---------|---------|
| `uavScenario` | Create simulation scenario | UAV Toolbox |
| `addMesh` | Add terrain, buildings, or custom meshes | UAV Toolbox |
| `uavPlatform` | Add UAV platform to scenario | UAV Toolbox |
| `updateMesh` | Set platform body mesh | UAV Toolbox |
| `uavSensor` | Attach sensor to platform | UAV Toolbox |
| `setup` | Initialize scenario for simulation | UAV Toolbox |
| `advance` | Step simulation forward one time step | UAV Toolbox |
| `updateSensors` | Update all sensors at current time | UAV Toolbox |
| `show3D` | 3D visualization | UAV Toolbox |
| `waypointTrajectory` | Define flight path from waypoints | Navigation Toolbox |
| `gpsSensor` | GPS noise model | Navigation Toolbox |
| `insSensor` | INS/IMU noise model | Navigation Toolbox |

## Patterns

### Create Scenario with Reference Location

```matlab
scene = uavScenario( ...
    "UpdateRate", 10, ...
    "StopTime", 60, ...
    "ReferenceLocation", [42.355 -71.066 0]);
```

`ReferenceLocation` is `[lat lon alt]` in degrees and meters. All local coordinates are relative to this origin. Set this before adding any meshes or platforms.

### Add Terrain (GMTED2010)

Use geographic coordinates with `UseLatLon=true`:

```matlab
latLim = [42.350 42.360];
lonLim = [-71.072 -71.060];
addMesh(scene, "terrain", {"gmted2010", latLim, lonLim}, [0.3 0.6 0.2], ...
    UseLatLon=true);
```

Or use local ENU coordinates (meters) without `UseLatLon`:

```matlab
xLim = [-500 500];
yLim = [-500 500];
addMesh(scene, "terrain", {"gmted2010", xLim, yLim}, [0.3 0.6 0.2]);
```

The geometry cell for terrain is **3 elements:** `{"gmted2010", xOrLatLim, yOrLonLim}`.

The `color` argument is **required** — it is not optional.

If user used addCustomTerrain to import DTED file with a terrain name, this terrain can be used in addition to gmted2010.

```matlab
addCustomTerrain("myterrain", "myterrain.dt1");
xLim = [-500 500];
yLim = [-500 500];
addMesh(scene, "terrain", {"myterrain", xLim, yLim}, [0.3 0.6 0.2]);
```

### Add Buildings (OSM File)

```matlab
osmFile = "boston_common.osm";
latLim = [42.350 42.360];
lonLim = [-71.072 -71.060];

addMesh(scene, "buildings", {osmFile, latLim, lonLim, 'auto'}, ...
    [0.6 0.6 0.6], UseLatLon=true);
```

Or use local ENU coordinates (meters) without `UseLatLon`:

```matlab
xLim = [-500 500];
yLim = [-500 500];
addMesh(scene, "buildings", {osmFile, xLim, yLim, 'auto'}, [0.3 0.6 0.2]);
```

The geometry cell for buildings is **4 elements:** `{osmFile, latOrXLim, lonOrYLim, height}`. `height` can either be 'auto' or a numerical scalar. Auto will snap buildings to terrain height if available.

The `color` argument is **required** — it is not optional.

### Add Platform with Mesh

```matlab
traj = waypointTrajectory( ...
    "Waypoints", [0 0 -50; 200 0 -50; 200 200 -50; 0 0 -50], ...
    "TimeOfArrival", [0 20 40 60], ...
    "ReferenceFrame", "NED");

plat = uavPlatform("UAV1", scene, "Trajectory", traj);
updateMesh(plat, "quadrotor", {1}, [0 0.4 0.8], [0 0 0], [0 1 0 0]);
```

`updateMesh` requires **all arguments**: `(platform, type, geometries, color, position, orientation)`.
- `geometries` — 1-element cell: `{scaleFactor}` for `"quadrotor"`/`"fixedwing"`, `{[L W H]}` for `"cuboid"`
- `color` — RGB triplet (required, not optional)
- `position` — `[x y z]` offset, use `[0 0 0]` for default
- `orientation` — quaternion `[w x y z]`, use `[0 1 0 0]` for NED scenarios (180-degree roll to flip z-down body frame upright)

Valid mesh types: `"fixedwing"`, `"quadrotor"`, `"cuboid"`, `"custom"`.

There is NO `"multirotor"` type — use `"quadrotor"` for any multirotor UAV.

### Attach Sensors (uavSensor Adaptor Pattern)

**Always use `uavSensor` to bind sensors to platforms.** Do not feed sensor models manually.

```matlab
% Create sensor model
gps = gpsSensor("SampleRate", 10, "ReferenceFrame", "NED");

% Bind to platform via uavSensor adaptor
gpsSensorObj = uavSensor("GPS", plat, gps, "UpdateRate", 10);
```

For INS:

```matlab
ins = insSensor;
insSensorObj = uavSensor("INS", plat, ins, "UpdateRate", 10);
```

Sensor `UpdateRate` must divide evenly into the scenario `UpdateRate`. For example, a 10 Hz scenario supports sensor rates of 1, 2, 5, or 10 Hz — not 100 Hz.

### Simulation Loop

```matlab
setup(scene);

while advance(scene)
    updateSensors(scene);

    % Read sensor data (3 outputs: isUpdated, timestamp, readings)
    [isUpdated, t, position, velocity, groundspeed, course] = read(gpsSensorObj);
    if isUpdated
        % position is 1x3 [lat lon alt] for gpsSensor
        gpsLLA = position;
    end

    % Read platform state directly
    [motion, lla] = read(plat);
    % motion: 1x16 vector [pos(3) orient(4) vel(3) acc(3) angvel(3)]
    % lla: [lat lon alt]
end
```

`read(sensor)` returns **variable number outputs:**
- `isUpdated` — logical, true when sensor has new data at this time step
- `t` — timestamp in seconds
- `sensorReadings1` to `sensorReadingsN` — sensor-specific output (`position, velocity, groundspeed, course` for `gpsSensor`)

`read(plat)` returns **exactly 2 outputs:**
- `motion` — 16-element vector: position(1:3), orientation quaternion(4:7), velocity(8:10), acceleration(11:13), angular velocity(14:16)
- `lla` — 3-element vector: [latitude, longitude, altitude]

### Visualize with show3D

```matlab
setup(scene);
ax = show3D(scene);

while advance(scene)
    updateSensors(scene);
    show3D(scene, "FastUpdate", true, "Parent", ax);
    drawnow limitrate
end
```

Use `"FastUpdate", true` after the first call for efficient animation.

### Trajectory Trail (Flight Path Line)

`show3D` only renders the UAV at its current position — it does NOT draw the flight path. To show the trajectory trail, create a line object once, then update its data each step:

```matlab
setup(scene);
[ax, plottedFrames] = show3D(scene);
hold(ax, "on");
% Draw trajectory in the platform's reference frame
trajLine = plot3(plottedFrames.(plat.ReferenceFrame), NaN, NaN, NaN, "r-", "LineWidth", 1.5);
hold(ax, "off");

% acceptable for short loops; pre-allocate for long simulations
xHist = []; yHist = []; zHist = [];
while advance(scene)
    show3D(scene, "FastUpdate", true, "Parent", ax);
    [motion, ~] = read(plat);
    xHist(end+1) = motion(1); 
    yHist(end+1) = motion(2);
    zHist(end+1) = motion(3);
    set(trajLine, "XData", xHist, "YData", yHist, "ZData", zHist);
    drawnow limitrate
end
```

Do NOT call `plot3` inside the loop — it creates a new graphics object each step and kills performance.

### Body-Frame Marker (Visibility in Large Scenes)

When scenes span 500m+, the platform mesh becomes invisible regardless of scale factor. Instead of inflating the scale (which distorts the mesh), parent a marker to the platform's body frame so it tracks at any zoom level:

```matlab
setup(scene);
[ax, plottedFrames] = show3D(scene);
hold(ax, "on");
bodyFrame = plottedFrames.UAV1.BodyFrame;
plot3(ax, 0, 0, 0, "r^", "MarkerSize", 15, "MarkerFaceColor", "r", ...
    "Parent", bodyFrame);
hold(ax, "off");

while advance(scene)
    show3D(scene, "FastUpdate", true, "Parent", ax);
    drawnow limitrate
end
```

Replace `UAV1` with the actual platform name. The marker moves with the UAV automatically via the parent transform.

## Gotchas

| Mistake | Consequence | Fix |
|---------|-------------|-----|
| `addMesh(...,latLim,lonLim)` without `UseLatLon=true` | 0 buildings imported, terrain at wrong location | Add `UseLatLon=true` when passing geographic coordinates |
| `updateMesh(plat,"multirotor",...)` | Error — invalid mesh type | Use `"quadrotor"` |
| `updateMesh` with `[1 0 0 0]` (identity quaternion) in NED scenario | Inverted or invisible mesh — body frame is z-down | Use `[0 1 0 0]` (180-degree roll) to flip mesh upright |
| `[pos, orient, vel] = read(plat)` | Error — too many outputs | Use `[motion, lla] = read(plat)` (2 outputs) |
| `[isUpdated, data] = read(sensor)` | Gets timestamp instead of readings | Use `[isUpdated, t, sensorReadings] = read(sensor)` (3 outputs) |
| Feeding `gpsSensor` manually each step | Works but bypasses the scenario framework | Use `uavSensor` adaptor + `updateSensors(scene)` |
| Missing `color` argument in `addMesh` | Error — not enough input arguments | Always provide RGB triplet as 4th argument |
| `waypointTrajectory` in ENU with NED platform | Error — reference frame mismatch | Set `"ReferenceFrame","NED"` on trajectory |
| Forgetting `setup(scene)` before loop | Sensors not initialized, no readings | Always call `setup(scene)` before `advance` |
| Sensor `UpdateRate` > scenario `UpdateRate` | Error — rate must divide evenly | Sensor rate must be ≤ scenario rate and divide evenly into it |

## Conventions

- **NED frame** is the default for `uavPlatform`. Match all trajectories and sensors to NED.
- **`ReferenceLocation`** must be set at scenario creation — it is read-only after construction.
- **`UpdateRate`** on the scenario controls the simulation time step. Sensor `UpdateRate` can differ (sensors skip steps when not due).
- **OSM files** must be downloaded separately (e.g., via Overpass API or export from openstreetmap.org). `addMesh("buildings",...)` expects a file path, not a URL.
- **`addCustomTerrain`** for DTED files when GMTED2010 resolution is insufficient.

---

Copyright 2026 The MathWorks, Inc.