Urban Scenario Benchmarks
UrbanMARL provides a comprehensive suite of multi-agent urban scenarios inheriting from UrbanScenario.
All scenarios run natively as vectorized PyTorch tensors on CPU and CUDA devices, supporting both direct TorchRL execution and BenchMARL benchmark experimentation.
Scenario Overview
Scenario Key |
Scenario Class |
Primary Objective & Scope |
|---|---|---|
|
|
3D UAV path planning & building collision avoidance |
|
|
Maintain dynamic LoS wireless links to ground UEs |
|
|
Maximize 3D geospatial mmWave area coverage |
|
|
End-to-end task offloading, M/M/c queuing & sojourn |
|
|
Dynamic user mobility (Manhattan / Hotspot tracking) |
|
|
360-degree LiDAR POMDP safe canyon navigation |
|
|
High-fidelity aerodynamics & 3D directional beamforming |
|
|
Baseline template for prototyping custom scenarios |
2. UAV-UE LoS Link Maintenance (uav_ue_los)
Description & Objective: UAVs coordinate 3D positions to maximize the Line-of-Sight (LoS) coverage ratio over ground IoT users, acting as airborne relays while avoiding building blockages.
Action Space: Continuous 3D velocity vector \(\mathbf{a}_i = [v_h, \phi, v_z]\).
Observation Space: 4-dimensional vector per UAV \(\mathbf{o}_i = [x_i, y_i, z_i, \text{Battery}_i]\).
Reward Function:
where \(\text{LoS}(i, j) \in \{0, 1\}\) is the binary Line-of-Sight indicator between UAV \(i\) and ground user \(j\) evaluated via 3D ray-casting over the urban heightmap.
3. 3D Spatial Area Coverage (coverage)
Description & Objective: UAVs learn cooperative spatial dispersion to maximize aggregate mmWave radio coverage over urban zones while penalizing UAVs that fly too close to one another.
Action Space: Continuous 3D velocity vector \(\mathbf{a}_i = [v_h, \phi, v_z]\).
Observation Space: 4-dimensional vector per UAV \(\mathbf{o}_i = [x_i, y_i, z_i, \text{Battery}_i]\).
Reward Function:
where \(d_{\text{thresh}}\) (default: 100 m) is the minimum inter-UAV safety distance threshold.
4. UAV-MEC Task Offloading (uavmec_offloading)
Description & Objective: Jointly optimizes 3D flight trajectories, dynamic DTLCM task offloading assignments, and multi-core MEC queuing resources to minimize system latency and energy dissipation while maximizing persistent sojourn coverage.
Action Space: Continuous velocity \([v_h, \phi, v_z]\).
Observation Space: 8-dimensional vector per UAV: position \((x, y, z)\), battery level, MEC server utilization, queue length, system latency, and completed task ratio.
Queuing & Wireless Channels: - Tasks arrive according to a Poisson process with data size \(D_k \in [0.5, 2.0]\text{ MB}\) and processing workload \(X_k = 1000\text{ cycles/bit}\). - Channel capacity follows Shannon’s theorem over 29 GHz mmWave carrier with ITU-R P.1410 path loss. - MEC computation follows an M/M/c queue with server utilization \(\rho_i\) and response delay \(W_{s, i}\).
Reward Function:
where \(\text{Sojourn}_i\) is Dr. Raddwan’s formulation quantifying persistent consecutive LoS coverage steps.
from urbanmarl.envs.base_env import UrbanEnv
env = UrbanEnv(
num_envs=32,
scenario="uavmec_offloading",
num_uavs=3,
num_ues=50,
frequency_ghz=29.0,
)
td = env.reset()
5. Dynamic Ground User Mobility (uav_mobile_ue)
Description & Objective: Ground users move continuously along urban street canyons under realistic mobility models. UAV swarms learn to track dynamic user clusters and maintain persistent communication links.
Mobility Engines: 1. Gauss-Markov Mobility: Correlated velocity updates with temporal memory factor \(\alpha_m \in [0, 1]\):
\[\mathbf{v}_j(t+1) = \alpha_m \mathbf{v}_j(t) + (1-\alpha_m) \bar{\mathbf{v}} + \sqrt{1-\alpha_m^2} \mathbf{n}(t)\]Manhattan Grid Mobility: Constrains users to street canyon intersections with turn probability matrices.
Hotspot Flocking: Models crowd gatherings drifting between urban points of interest.
Random Waypoint (RWP): Standard baseline random destination model with pause times.
Action Space: Continuous velocity \([v_h, \phi, v_z]\).
Observation Space: UAV coordinates, battery, ground user centroid positions, and active LoS matrix.
Reward Function:
from urbanmarl.envs.base_env import UrbanEnv
env = UrbanEnv(
num_envs=16,
scenario="uav_mobile_ue",
num_uavs=3,
num_ues=20,
mobility_model="gauss_markov",
)
7. High-Fidelity Physics & Propagation (uavmec_advanced_physics)
Description & Objective: Combines rigorous rotary-wing aerodynamic propulsion power dissipation with 3GPP TR 38.901 3D directional beamforming antennas and multi-core MEC queuing.
Aerodynamic Propulsion Power Model (Zeng et al., IEEE TWC): Models flight power dissipation as a function of 3D speed \(V = \|\mathbf{v}_i\|\):
\[P(V) = \underbrace{P_0 \left(1 + \frac{3 V^2}{U_{\text{tip}}^2}\right)}_{\text{Blade Profile Power}} + \underbrace{P_i \left(\sqrt{1 + \frac{V^4}{4 v_0^4}} - \frac{V^2}{2 v_0^2}\right)^{1/2}}_{\text{Induced Flight Power}} + \underbrace{\frac{1}{2} d_0 \rho s A V^3}_{\text{Parasite Drag Power}}\]where \(P_0\) is blade profile power in hover, \(P_i\) is induced hover power, \(U_{\text{tip}}\) is rotor tip speed, \(v_0\) is mean rotor induced velocity, \(d_0\) is fuselage drag ratio, \(\rho\) is air density (\(1.225\text{ kg/m}^3\)), and \(s\) is rotor solidity.
3GPP TR 38.901 3D Directional Antennas: Computes azimuth and elevation angle attenuation:
\[A(\theta, \phi) = -\min\left(-(A_H(\phi) + A_V(\theta)), A_{\max}\right)\]yielding realistic directional beamforming gains for mmWave access links.
Action Space: Continuous velocity \([v_h, \phi, v_z]\).
Observation Space: UAV kinematics, aerodynamic battery consumption rate, 3D directional achievable data rates, and multi-core MEC queue telemetry.
Reward Function:
from urbanmarl.envs.base_env import UrbanEnv
env = UrbanEnv(
num_envs=32,
scenario="uavmec_advanced_physics",
num_uavs=3,
num_ues=10,
frequency_ghz=29.0,
)
8. Default Scenario (default)
Description:
Standard baseline scenario template inheriting directly from NavigationScenario. Serves as a reference implementation for new researchers creating novel custom tasks.
Dynamic Scenario Auto-Registration
UrbanMARL features an automated discovery system in urbanmarl.scenarios.
Any new scenario placed in the urbanmarl/scenarios/ directory that inherits from UrbanScenario is automatically discovered, registered, and available across both TorchRL and BenchMARL without modifying any registry code.
Creating a Custom Scenario
To create a new research scenario:
Create a new Python file in
urbanmarl/scenarios/(e.g.urbanmarl/scenarios/my_scenario.py).Subclass
UrbanScenarioand define the required interface methods:
# urbanmarl/scenarios/my_scenario.py
from typing import Tuple, Optional
import torch
from torchrl.data import Composite, Unbounded
from urbanmarl.scenarios.base import UrbanScenario
class Scenario(UrbanScenario):
"""Custom urban research scenario."""
def _reset_all(self, env, tensordict=None, **kwargs):
env.uav_agents_pos = env._env.gen_pos(
num_pos=env.n_uavs, min_z=25.0, max_z=100.0, outdoor=True
)
env.uav_battery = torch.full((env.batch_size[0], env.n_uavs, 1), 100.0, device=env.device)
env.uav_collisions = torch.zeros((env.batch_size[0], env.n_uavs, 1), dtype=torch.bool, device=env.device)
def _reset_at(self, env, env_index: int, tensordict=None, **kwargs):
# Reset single environment instance in the batch
pass
def process_actions(self, env, tensordict):
# Update flight kinematics
pass
def observation(self, env) -> torch.Tensor:
return torch.cat([env.uav_agents_pos, env.uav_battery], dim=-1)
def observation_spec(self, env, group: str) -> Composite:
return Unbounded(shape=torch.Size([4]), dtype=torch.float32, device=env.device)
def action_spec(self, env, group: str) -> Composite:
from torchrl.data.tensor_specs import Bounded
return Bounded(low=-1.0, high=1.0, shape=torch.Size([3]), dtype=torch.float32, device=env.device)
def reward(self, env, group: str) -> torch.Tensor:
return -env.uav_collisions.float()
def done(self, env) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
terminated = env.uav_collisions.any(dim=1)
truncated = env.current_step >= env.max_steps
return terminated | truncated, terminated, truncated
def _render(self, env, mode="rgb_array") -> dict:
return {"uav_positions": env.uav_agents_pos[0].detach().cpu()}
The scenario is now automatically available:
from urbanmarl.envs.base_env import UrbanEnv
from urbanmarl.scenarios import list_scenarios
print(list_scenarios()) # 'my_scenario' appears automatically!
env = UrbanEnv(scenario="my_scenario", num_envs=8)