Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions examples/airsim/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# AirSim example

This directory contains a minimal Scenic example for controlling a drone in
[Microsoft AirSim](https://github.com/microsoft/AirSim).

The example has been tested with AirSim 1.8.1 on Ubuntu 22.04. AirSim requires
a graphical environment and is not supported on macOS.

## Install the Python dependencies

Create and activate a virtual environment, then install Scenic from the
repository:

```bash
python3 -m venv .venv-airsim
source .venv-airsim/bin/activate
python -m pip install --upgrade pip wheel
python -m pip install -e .
```

Install the AirSim client and its additional dependencies:

```bash
python -m pip install msgpack-rpc-python promise
python -m pip install --no-build-isolation airsim==1.8.1
```

The following NumPy and OpenCV versions were used during testing:

```bash
python -m pip install --force-reinstall \
numpy==1.26.4 \
opencv-contrib-python==4.10.0.84
```

Check the resulting environment:

```bash
python -m pip check
```

## Start AirSim

Download or build an AirSim environment. For example, launch the AirSim 1.8.1
Blocks environment with the settings included in this directory:

```bash
/path/to/Blocks.sh \
-settings="/path/to/Scenic/examples/airsim/settings/simple_drone_settings.json" \
-windowed \
-ResX=640 \
-ResY=480 \
-NoVSync
```

These window settings are conservative defaults that work well on a remote
desktop. They can be adjusted for the available display and hardware.

Run AirSim from a graphical desktop session and leave it open while Scenic is
running.

## Generate world information

The Scenic AirSim model requires information about the objects and assets in
the selected AirSim environment.

Start AirSim first. Then, from the Scenic repository, run:

```bash
python src/scenic/simulators/airsim/generators/generateWorldInfo.py \
--outputDirectory "/path/to/blocks-world-info"
```

The output directory must not already exist. Generating the meshes may take
several minutes.

The resulting directory contains:

```text
worldInfo.json
objectMeshes/
assets/
```

Keep this generated directory outside the Scenic repository. Pass its location
to Scenic using the `worldInfoPath` parameter.

## Run the patrol example

With AirSim running, open another terminal, activate the Python environment,
and run:

```bash
scenic examples/airsim/patrol.scenic \
--simulate \
--count 1 \
--time 30 \
--param worldInfoPath "/path/to/blocks-world-info"
```

The example creates one drone and sends it through a fixed sequence of patrol
points.
25 changes: 25 additions & 0 deletions examples/airsim/flyFromBlockToBlock.scenic
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
param worldOffset = Vector(0, 0, 50)

model scenic.simulators.airsim.model


ground = getPrexistingObj("ground")
centerArea = RectangularRegion(Vector(0, 0, 30), 0, 100, 100)

platforms = []
for i in range(10):
platforms.append(new StaticObj on ground,
contained in centerArea,
with assetName "Cone",
with width Range(3, 10),
with length Range(3, 10),
with height 10)

points = []
for platform in platforms:
platformRegion = platform.occupiedSpace.boundingPolygon
point = new Point on platformRegion
points.append(new Point at point.position + Vector(0, 0, 15))

drone = new Drone at Uniform(*points) + Vector(0, 0, 5),
with behavior Patrol(points, True)
28 changes: 28 additions & 0 deletions examples/airsim/followDrone.scenic
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import math

param worldOffset = Vector(0, 0, 50)
param timestep = 0.1

model scenic.simulators.airsim.model


def magnitude(v):
return math.hypot(v.x, v.y, v.z)


behavior Follow(target, speed=5, tolerance=2, offset=(0, 0, 1)):
while True:
targetPosition = target.position + offset
velocity = targetPosition - self.position
distance = magnitude(velocity)
if distance > tolerance:
velocity = (velocity / distance) * speed
take SetVelocity(velocity)
wait


drone1 = new Drone at (0, 0, 10),
with behavior Patrol([(0, 0, 10), (0, 10, 10), (10, 10, 10), (10, 0, 10)], True, speed=2)

drone2 = new Drone at (0, 100, 10),
with behavior Follow(drone1, 5, 5, (0, 0, 0))
29 changes: 29 additions & 0 deletions examples/airsim/functionalTerrain.scenic
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import math

param worldOffset = Vector(0, 0, 50)
param timestep = 0.1

model scenic.simulators.airsim.model


ground = getPrexistingObj("ground")

ego = new StaticObj on ground,
with assetName "Cone",
with width 10,
with length 10,
with height 10

positions = []
for i in range(10):
pos = Vector(i * 3, math.cos(i) * Uniform(1, 3), 1)
positions.append(pos + Vector(0, 0, 3))

new StaticObj at pos + Vector(0, 0, 1),
with assetName "Cone",
with width 1,
with length 1,
with height 1

drone = new Drone on positions[0],
with behavior Patrol(positions, smooth=False, speed=5)
8 changes: 8 additions & 0 deletions examples/airsim/multiDrone.scenic
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
param worldOffset = Vector(0, 0, 50)

model scenic.simulators.airsim.model


for i in range(3):
new Drone at (Range(-100, 100), Range(-100, 100), Range(0, 50)),
with behavior FlyToPosition((Range(-100, 100), Range(-100, 100), Range(0, 50)))
9 changes: 9 additions & 0 deletions examples/airsim/patrol.scenic
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# NOTE: add your world info path here
# param worldInfoPath = "[YOUR PATH HERE]"
param worldOffset = Vector(0,0,50) # blocks world offset

model scenic.simulators.airsim.model


drone1 = new Drone at (0,0,10),
with behavior Patrol([(-10,20,10),(10,40,10),(-10,40,10),(-10,20,10),(10,20,10),(10,40,10),(-1,40,10)],True)
Loading