Launching Isaac Sim from AppLauncher
====================================

.. currentmodule:: omni.isaac.orbit

In this tutorial, we will dive into the :class:`app.AppLauncher` class to configure the simulator using
CLI arguments and environment variables (envars). Particularly, we will demonstrate how to use :class:`~app.AppLauncher`
to enable livestreaming and configure the :class:`omni.isaac.kit.SimulationApp` instance it wraps,
while also allowing user-provided options.

Motivation
----------

The :class:`~app.AppLauncher` is a wrapper for :class:`~omni.isaac.kit.SimulationApp` to simplify its configuration.
The :class:`~omni.isaac.kit.SimulationApp` has many extensions that must be loaded to enable different capabilities, and some of these extensions are order- and inter-dependent.
Additionally, there are startup options such as ``headless`` which must be set at instantiation time, and which have an implied relationship with
some extensions, e.g. the livestreaming extensions. The :class:`~app.AppLauncher` presents an interface that can handle these extensions and startup options
in a portable manner across a variety of use cases. To achieve this, we offer CLI and envar flags which can be merged with user-defined CLI args,
while passing forward arguments intended for :class:`~omni.isaac.kit.SimulationApp`.


The Code
~~~~~~~~

The tutorial corresponds to the ``launch_app.py`` script in the ``orbit/source/standalone/tutorials/00_sim`` directory.

.. dropdown:: Code for launch_app.py
   :icon: code

   .. literalinclude:: ../../../../source/standalone/tutorials/00_sim/launch_app.py
      :language: python
      :emphasize-lines: 17-41
      :linenos:

The Code Explained
~~~~~~~~~~~~~~~~~~

:class:`~app.AppLauncher` is designed to be compatible with custom CLI args that users need for their own scripts,
while still providing a portable CLI interface. In this tutorial, a standard :class:`argparse.ArgumentParser` is instantiated
and given the script-specific ``--size`` argument, as well as the arguments ``--height`` and ``--width``. The latter
are ingested by :class:`~omni.isaac.kit.SimulationApp`.

The argument ``--size`` is not used by :class:`~app.AppLauncher`, but will merge seamlessly with the :class:`~app.AppLauncher`
interface. In-script arguments can be merged with the :class:`~app.AppLauncher` interface via the :meth:`~app.AppLauncher.add_app_launcher_args` method,
which will return a modified :class:`~argparse.ArgumentParser` with the :class:`~app.AppLauncher` arguments appended. This can then be processed
into an :class:`argparse.Namespace` using the standard :meth:`argparse.ArgumentParser.parse_args` method and passed directly to :class:`~app.AppLauncher` for instantiation.
This illustrates only one of several ways of passing arguments to :class:`~app.AppLauncher`, please consult its documentation page to see further options.

.. literalinclude::  ../../../../source/standalone/tutorials/00_sim/launch_app.py
   :language: python
   :start-at: import argparse
   :end-at: simulation_app = app_launcher.app

To illustrate this process, we can pass the ``--help`` argument and see the combined outputs of our custom arguments and
those from :class:`~app.AppLauncher`.

.. code-block:: console

   ./orbit.sh -p source/standalone/tutorials/00_sim/launch_app.py --help

   [INFO] Using python from: /isaac-sim/python.sh
   [INFO][AppLauncher]: The argument 'width' will be used to configure the SimulationApp.
   [INFO][AppLauncher]: The argument 'height' will be used to configure the SimulationApp.
   usage: launch_app.py [-h] [--size SIZE] [--width WIDTH] [--height HEIGHT] [--headless] [--livestream {0,1,2,3}] [--ros {0,1,2}]
                        [--offscreen_render]

   Tutorial on running IsaacSim via the AppLauncher.

   options:
   -h, --help            show this help message and exit
   --size SIZE           Side-length of cuboid
   --width WIDTH         Width of the viewport and generated images. Defaults to 1280
   --height HEIGHT       Height of the viewport and generated images. Defaults to 720

   app_launcher arguments:
   --headless            Force display off at all times.
   --livestream {0,1,2,3}
                         Force enable livestreaming. Mapping corresponds to that for the "LIVESTREAM" environment variable.
   --ros {0,1,2}         Enable ROS middleware. Mapping corresponds to that for the "ROS_ENABLED" environment variable
   --offscreen_render    Enable offscreen rendering when running without a GUI.

This readout details the ``--size``, ``--height``, and ``--width`` arguments defined in the script directly, as well as the :class:`~app.AppLauncher` arguments.
An ``[INFO]`` message preceding the help output also reads out which of these arguments are going to be interpreted as arguments to the :class:`~omni.isaac.kit.SimulationApp` instance which :class:`~app.AppLauncher` wraps,
in this instance ``--height`` and ``--width``. These are classified as such because they match the name and type of an argument which can be processed by :class:`~omni.isaac.kit.SimulationApp`.
Please refer to the `specification`_ for such arguments for more examples.
As noted in the help message, the :class:`~app.AppLauncher` arguments correspond to the envars described in :mod:`omni.isaac.orbit.app`. Providing any of these arguments is equivalent to
running the script in a shell environment where the corresponding envar is set- :class:`~app.AppLauncher` envars are simply a convenience to provide session-persistent configurations,
and can be set in the user's ``.bashrc`` for persistent settings between sessions. In the case where these arguments are provided, they will override their corresponding envar, as we
will demonstrate below.

These arguments can be used with any script that starts the simulation using :class:`~app.AppLauncher`, with one exception, ``--offscreen_render``.
The :class:`omni.isaac.orbit.sim.SimulationContext`  class controls many aspects of simulation execution, including the rendering pipeline. This makes it required when we
want to use the ``--offscreen_render`` argument, because ``--offscreen_render`` pipeline depends on behavior within :class:`~omni.isaac.orbit.sim.SimulationContext`.
For more information on the ``--offscreen_render`` flag, please see the :class:`~app.AppLauncher` API doc.

.. literalinclude::  ../../../../source/standalone/tutorials/00_sim/launch_app.py
   :language: python
   :start-at: def main():
   :end-at: sim = sim_utils.SimulationContext(sim_cfg)

The Code Execution
~~~~~~~~~~~~~~~~~~

We will now run the example script:

.. code-block:: console

   LIVESTREAM=1 ./orbit.sh -p source/standalone/tutorials/00_sim/launch_app.py --size 0.5

This will spawn a 0.5m\ :sup:`3` volume cuboid in the simulation. No GUI will appear, equivalent
to if we had passed the ``--headless`` flag because headlessness is implied by our ``LIVESTREAM`` envar. If a
visualization is desired, we could get one via Isaac's `Native Livestreaming`_. The process can be killed by pressing ``Ctrl+C`` in the launching terminal.


Now we will look at how :class:`~app.AppLauncher` handles conflicting commands:

.. code-block:: console

   export LIVESTREAM=0
   ./orbit.sh -p source/standalone/tutorials/00_sim/launch_app.py --size 0.5 --livestream 1

This will cause the same behavior as in the previous run, because although we have set ``LIVESTREAM=0``
in our envars, CLI args such as ``--livestream`` take precedence in determining behavior. The process can
be killed by pressing ``Ctrl+C`` in the launching terminal.

Finally, we will examine passing arguments to :class:`~omni.isaac.kit.SimulationApp` through :class:`~app.AppLauncher`:

.. code-block:: console

   export LIVESTREAM=1
   ./orbit.sh -p source/standalone/tutorials/00_sim/launch_app.py --size 0.5 --width 1920 --height 1080

This will cause the same behavior as before, but now the viewport will be rendered at 1920x1080p resolution.
This can be useful when we want to gather high-resolution video, or we can specify a lower resolution if we
want our simulation to be more performant. The process can be killed by pressing ``Ctrl+C`` in the launching terminal.

.. _specification: https://docs.omniverse.nvidia.com/py/isaacsim/source/extensions/omni.isaac.kit/docs/index.html#omni.isaac.kit.SimulationApp.DEFAULT_LAUNCHER_CONFIG
.. _Native Livestreaming: https://docs.omniverse.nvidia.com/isaacsim/latest/installation/manual_livestream_clients.html#omniverse-streaming-client
