Skip to content

Configuration

from nexus_uav import LaunchConfig, Catalog

LaunchConfig

Bases: _Base

The sim's fixed standup properties: what the sim is, not what happens to it.

Dynamics, such as faults and moving actors, are control-API verbs, not config. Small in the common case: the vehicle and the scene, and the catalog fills in the rest.

vehicle class-attribute instance-attribute

vehicle: str | None = None

The vehicle to fly: a catalog name handle (--vehicle astro_max_fpv), or a path to a local vehicle Universal Scene Description (USD) file.

None until set; a launch that still names none fails to resolve.

catalog class-attribute instance-attribute

catalog: str | None = None

Path to the catalog that extends the bundled and installed ones for this run, the --catalog value.

None takes the nearest nexus.catalog.yaml in the working directory or a directory over it, and only the bundled and installed catalogs when no directory holds one.

scene class-attribute instance-attribute

scene: str | None = None

Name of the static scene to stand up, keyed into the catalog's scenes, or a local scene Universal Scene Description (USD) path (a converted mesh/splat, flown as the visual world).

None until set; a launch that still names none fails to resolve.

layer class-attribute instance-attribute

layer: str | None = None

Path to an override layer, a local Universal Scene Description (USD) file the run composes over the vehicle and the scene, the --layer value.

Its opinions win over theirs: it changes a declared value, selects a variant, or drops a declaration, such as the PX4 Software In The Loop (SITL) peer's to fly an autopilot started elsewhere, or moves the scene's geodetic origin on its PhysicsScene prim. The receipt records its sha256 beside the vehicle's. None flies the vehicle and the scene as their files declare them.

runtime class-attribute instance-attribute

runtime: Runtime = Field(default_factory=Runtime)

Solver, device, timestep, and seed settings for the run.

Defaults to the auto device with the mujoco solver.

output class-attribute instance-attribute

output: Output = Field(default_factory=Output)

The Rerun recording the run produces.

Defaults to an Output with no recording and no viewer.

from_dict classmethod

from_dict(data: dict | None) -> LaunchConfig

Build and validate a config from a plain dict.

PARAMETER DESCRIPTION
data

The mapping of config fields. None, or an empty dict, yields a fully defaulted config.

TYPE: dict | None

RETURNS DESCRIPTION
LaunchConfig

The validated LaunchConfig.

RAISES DESCRIPTION
ValidationError

If data has unknown keys, which extra="forbid" rejects, or values that fail validation.

Source code in nexus_uav/_src/config/models.py
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
@classmethod
def from_dict(cls, data: dict | None) -> LaunchConfig:
    """Build and validate a config from a plain dict.

    Args:
        data: The mapping of config fields. ``None``, or an empty dict, yields a
            fully defaulted config.

    Returns:
        The validated ``LaunchConfig``.

    Raises:
        pydantic.ValidationError: If ``data`` has unknown keys, which ``extra="forbid"`` rejects,
            or values that fail validation.
    """
    return cls.model_validate(data or {})

from_yaml classmethod

from_yaml(path: str | Path) -> LaunchConfig

Build and validate a config from a YAML file.

PARAMETER DESCRIPTION
path

Path to the YAML launch-config file.

TYPE: str | Path

RETURNS DESCRIPTION
LaunchConfig

The validated LaunchConfig.

RAISES DESCRIPTION
ValidationError

If the parsed document fails validation.

Source code in nexus_uav/_src/config/models.py
140
141
142
143
144
145
146
147
148
149
150
151
152
153
@classmethod
def from_yaml(cls, path: str | pathlib.Path) -> LaunchConfig:
    """Build and validate a config from a YAML file.

    Args:
        path: Path to the YAML launch-config file.

    Returns:
        The validated ``LaunchConfig``.

    Raises:
        pydantic.ValidationError: If the parsed document fails validation.
    """
    return cls.from_dict(yaml.safe_load(pathlib.Path(path).read_text()))

set_vehicle

set_vehicle(vehicle: str) -> LaunchConfig

Set the vehicle to fly in place: a catalog name handle or a local .usd path.

resolve() reads a value with a path separator or a .usd suffix as a file and every other value as a catalog name, so this setter takes a --vehicle command-line value unchanged. Sim and the command-line tool both select through it, so the two behave identically.

PARAMETER DESCRIPTION
vehicle

The catalog name or the local .usd path.

TYPE: str

RETURNS DESCRIPTION
LaunchConfig

self, so calls chain.

Source code in nexus_uav/_src/config/models.py
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
def set_vehicle(self, vehicle: str) -> LaunchConfig:
    """Set the vehicle to fly in place: a catalog ``name`` handle or a local ``.usd`` path.

    ``resolve()`` reads a value with a path separator or a ``.usd`` suffix as a file and every other
    value as a catalog name, so this setter takes
    a ``--vehicle`` command-line value unchanged. ``Sim`` and the command-line tool both select
    through it, so the two behave identically.

    Args:
        vehicle: The catalog name or the local ``.usd`` path.

    Returns:
        ``self``, so calls chain.
    """
    self.vehicle = vehicle
    return self

set_scene

set_scene(scene: str) -> LaunchConfig

Set the scene name in place.

PARAMETER DESCRIPTION
scene

The scene name to key into the catalog's scenes.

TYPE: str

RETURNS DESCRIPTION
LaunchConfig

self, so calls chain.

Source code in nexus_uav/_src/config/models.py
172
173
174
175
176
177
178
179
180
181
182
def set_scene(self, scene: str) -> LaunchConfig:
    """Set the scene name in place.

    Args:
        scene: The scene name to key into the catalog's ``scenes``.

    Returns:
        ``self``, so calls chain.
    """
    self.scene = scene
    return self

Catalog

Bases: _Base

The checked-in vehicle/scene catalog and where its blobs live.

Resolution is by name: a launch names a :class:VehicleVariant and a scene. Built by :func:load_catalog from the bundled catalog.yaml, extended by the catalog of each installed package and by the catalog a project beside the framework keeps.

assets class-attribute instance-attribute

assets: Assets = Field(default_factory=Assets)

Where this catalog's blobs live; see :class:Assets.

vehicles class-attribute instance-attribute

vehicles: dict[str, VehicleVariant] = Field(
    default_factory=dict
)

The catalog of vehicle variants, keyed by name (the key a LaunchConfig.vehicle refers to).

Empty by default; an empty catalog resolves no name.

scenes class-attribute instance-attribute

scenes: dict[str, Scene] = Field(default_factory=dict)

The available scenes, keyed by name (the key a LaunchConfig.scene refers to).

Empty by default.

from_dict classmethod

from_dict(data: dict | None) -> Catalog

Build and validate a catalog from a plain dict.

PARAMETER DESCRIPTION
data

The mapping of catalog fields. None, or an empty dict, yields an empty, fully defaulted catalog.

TYPE: dict | None

RETURNS DESCRIPTION
Catalog

The validated Catalog.

RAISES DESCRIPTION
ValidationError

If data has unknown keys or values that fail validation.

CatalogError

If a compact usd entry has no assets.base to complete it.

Source code in nexus_uav/_src/config/catalog.py
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
@classmethod
def from_dict(cls, data: dict | None) -> Catalog:
    """Build and validate a catalog from a plain dict.

    Args:
        data: The mapping of catalog fields. ``None``, or an empty dict, yields an empty,
            fully defaulted catalog.

    Returns:
        The validated ``Catalog``.

    Raises:
        pydantic.ValidationError: If ``data`` has unknown keys or values that fail
            validation.
        CatalogError: If a compact ``usd`` entry has no ``assets.base`` to complete it.
    """
    return cls.model_validate(data or {})

from_yaml classmethod

from_yaml(path: str | Path | None = None) -> Catalog

Build and validate a catalog from a YAML file.

PARAMETER DESCRIPTION
path

Path to the catalog YAML. None loads the package's bundled catalog.yaml.

TYPE: str | Path | None DEFAULT: None

RETURNS DESCRIPTION
Catalog

The validated Catalog.

RAISES DESCRIPTION
ValidationError

If the parsed document fails validation.

CatalogError

If a compact usd entry has no assets.base to complete it.

Source code in nexus_uav/_src/config/catalog.py
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
@classmethod
def from_yaml(cls, path: str | pathlib.Path | None = None) -> Catalog:
    """Build and validate a catalog from a YAML file.

    Args:
        path: Path to the catalog YAML. ``None`` loads the package's bundled
            ``catalog.yaml``.

    Returns:
        The validated ``Catalog``.

    Raises:
        pydantic.ValidationError: If the parsed document fails validation.
        CatalogError: If a compact ``usd`` entry has no ``assets.base`` to complete it.
    """
    path = pathlib.Path(path) if path is not None else _DEFAULT_CATALOG
    return cls.from_dict(yaml.safe_load(path.read_text()))

stack

stack(name: str) -> tuple[AssetRef, list[AssetRef]]

The file a vehicle entry rests on and the layers over it, strongest first.

A flat entry is its own file with no layers. A composed entry's layers come first, then its base's, down the chain to the flat entry at the bottom.

PARAMETER DESCRIPTION
name

The vehicle's key in :attr:vehicles.

TYPE: str

RETURNS DESCRIPTION
tuple[AssetRef, list[AssetRef]]

The flat entry's usd at the bottom of the chain, and the layers over it, strongest first.

RAISES DESCRIPTION
NoMatchError

If the catalog names no vehicle name. The message lists the vehicles it names.

CatalogError

If an entry on the chain names a base that no catalog defines, or the chain loops.

Source code in nexus_uav/_src/config/catalog.py
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
def stack(self, name: str) -> tuple[AssetRef, list[AssetRef]]:
    """The file a vehicle entry rests on and the layers over it, strongest first.

    A flat entry is its own file with no layers. A composed entry's layers come first, then its
    base's, down the chain to the flat entry at the bottom.

    Args:
        name: The vehicle's key in :attr:`vehicles`.

    Returns:
        The flat entry's ``usd`` at the bottom of the chain, and the layers over it, strongest first.

    Raises:
        NoMatchError: If the catalog names no vehicle ``name``. The message lists the vehicles it names.
        CatalogError: If an entry on the chain names a base that no catalog defines, or the chain loops.
    """
    if name not in self.vehicles:
        raise NoMatchError(f"no vehicle named {name!r}; catalog names: {list(self.vehicles)}")
    layers: list[AssetRef] = []
    chain = [name]
    while True:
        entry = self.vehicles[chain[-1]]
        if entry.usd is not None:
            return entry.usd, layers
        layers.extend(entry.layers)
        if entry.base not in self.vehicles:
            raise CatalogError(
                f"vehicle {chain[-1]!r} names base {entry.base!r}, which no catalog defines; "
                f"catalog names: {list(self.vehicles)}"
            )
        if entry.base in chain:
            raise CatalogError(f"vehicle {name!r} rests on a loop of bases: {' -> '.join([*chain, entry.base])}")
        chain.append(entry.base)

fetch_vehicle

fetch_vehicle(name: str) -> Path

Fetch the named vehicle's Universal Scene Description (USD) file and return its local path.

The file lands in the asset cache, which $NEXUS_ASSET_CACHE overrides, and a later call reads it from there with no download. A composed entry's base and layers each land there, and the path is a root file in the cache that stacks them, which opens as the composed vehicle. A project that loads a catalog vehicle into a simulator of its own, such as Isaac Lab, opens the returned file.

PARAMETER DESCRIPTION
name

The vehicle's key in :attr:vehicles, such as astro_max_base.

TYPE: str

RETURNS DESCRIPTION
Path

The path of the cached file, whose sha256 matches the catalog entry, or of the root file that

Path

stacks a composed entry's layers over its base.

RAISES DESCRIPTION
NoMatchError

If the catalog names no vehicle name. The message lists the vehicles it names.

CatalogError

If an entry on the chain names a base that no catalog defines, or the chain loops.

ValueError

If a fetched file's sha256 differs from the catalog entry's.

Source code in nexus_uav/_src/config/catalog.py
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
def fetch_vehicle(self, name: str) -> pathlib.Path:
    """Fetch the named vehicle's Universal Scene Description (USD) file and return its local path.

    The file lands in the asset cache, which ``$NEXUS_ASSET_CACHE`` overrides, and a later call reads
    it from there with no download. A composed entry's base and layers each land there, and the path
    is a root file in the cache that stacks them, which opens as the composed vehicle. A project that
    loads a catalog vehicle into a simulator of its own, such as Isaac Lab, opens the returned file.

    Args:
        name: The vehicle's key in :attr:`vehicles`, such as ``astro_max_base``.

    Returns:
        The path of the cached file, whose sha256 matches the catalog entry, or of the root file that
        stacks a composed entry's layers over its base.

    Raises:
        NoMatchError: If the catalog names no vehicle ``name``. The message lists the vehicles it names.
        CatalogError: If an entry on the chain names a base that no catalog defines, or the chain loops.
        ValueError: If a fetched file's sha256 differs from the catalog entry's.
    """
    blob, layers = self.stack(name)
    path = fetch_asset(blob.model_dump(exclude_none=True))
    if not layers:
        return path
    fetched = [(fetch_asset(layer.model_dump(exclude_none=True)), layer.sha256) for layer in layers]
    return stack_layers(fetched, path, blob.sha256)