Introduce new, single-entrypoint installation script

This commit is contained in:
Cem Gökmen 2024-09-27 00:00:23 -07:00
parent 8659a0d1eb
commit d992dc1c9b
4 changed files with 346 additions and 161 deletions

View File

@ -23,7 +23,7 @@ def main():
print(
f"If you want to install data under a different path, please change the DATA_PATH variable in omnigibson/macros.py and rerun omnigibson/download_datasets.py."
)
if click.confirm("Do you want to continue?"):
if click.confirm("Do you want to continue?", default=True):
# Only download if the dataset path doesn't exist
if not dataset_exists:
print("Downloading dataset...")

345
omnigibson/install.py Normal file
View File

@ -0,0 +1,345 @@
import os
import platform
import subprocess
import sys
import tempfile
import urllib.request
from pathlib import Path
from typing import Optional
import click
import pip
from omnigibson.macros import gm
from omnigibson.utils.asset_utils import download_assets, download_og_dataset
# List of NVIDIA PyPI packages needed for OmniGibson
ISAAC_SIM_PACKAGES = [
"omniverse_kit-106.1.0.140981",
"isaacsim_kernel-4.2.0.2",
"isaacsim_app-4.2.0.2",
"isaacsim_core-4.2.0.2",
"isaacsim_gui-4.2.0.2",
"isaacsim_utils-4.2.0.2",
"isaacsim_storage-4.2.0.2",
"isaacsim_asset-4.2.0.2",
"isaacsim_sensor-4.2.0.2",
"isaacsim_robot_motion-4.2.0.2",
"isaacsim_robot-4.2.0.2",
"isaacsim_benchmark-4.2.0.2",
"isaacsim_code_editor-4.2.0.2",
"isaacsim_ros1-4.2.0.2",
"isaacsim_cortex-4.2.0.2",
"isaacsim_example-4.2.0.2",
"isaacsim_replicator-4.2.0.2",
"isaacsim_rl-4.2.0.2",
"isaacsim_robot_setup-4.2.0.2",
"isaacsim_ros2-4.2.0.2",
"isaacsim_template-4.2.0.2",
"isaacsim_test-4.2.0.2",
"isaacsim-4.2.0.2",
"isaacsim_extscache_physics-4.2.0.2",
"isaacsim_extscache_kit-4.2.0.2",
"isaacsim_extscache_kit_sdk-4.2.0.2",
]
BASE_URL = "https://pypi.nvidia.com"
def _find_isaac_sim_path():
"""Try to find the path of a launcher-based Isaac Sim installation."""
if platform.system() == "Windows":
base_path = Path.home() / "AppData" / "Local" / "ov" / "pkg"
else:
base_path = Path.home() / ".local" / "share" / "ov" / "pkg"
# If the pkg dir is missing, we definitely can't find an Isaac Sim installation
if not base_path.exists():
return None
isaac_dirs = list(base_path.glob("isaac*"))
if not isaac_dirs:
return None
return isaac_dirs[-1]
def _get_filename(package: str, temp_dir: Path):
if platform.system() == "Windows":
return temp_dir / f"{package}-cp310-win_amd64.whl"
return temp_dir / f"{package}-cp310-none-manylinux_2_34_x86_64.whl"
def _download_package(url: str, filename: Path):
try:
urllib.request.urlretrieve(url, filename)
except Exception as e:
raise ValueError(f"Failed to download {url}") from e
def _rename_if_necessary(filename: Path):
"""
Rename the file if the system's GLIBC version is older than the one used in the NVIDIA PyPI packages.
This is permissible because the manylinux wheels are compatible with older GLIBC versions even though
the filename suggests not - so we apply this hacky workaround. This allows pip to try to install them.
"""
if platform.system() == "Linux" and _is_glibc_older():
return filename.with_name(filename.name.replace("manylinux_2_34", "manylinux_2_31"))
return filename
def _is_glibc_older():
"""Check if the system's GLIBC version is older than the one used in the NVIDIA PyPI packages."""
try:
dist_info = subprocess.check_output(["ldd", "--version"]).decode("utf-8")
if any(version in dist_info for version in ["2.31", "2.32", "2.33"]):
return True
elif any(version in dist_info for version in ["2.34", "2.35", "2.36", "2.37", "2.38", "2.39"]):
return False
else:
raise ValueError("Incompatible GLIBC version")
except subprocess.CalledProcessError:
raise ValueError("Failed to check GLIBC version. `ldd` was not accessible. Try running it yourself to see why.")
def _pip_install(filename: Path):
"""Install a package using pip."""
try:
pip.main(["install", str(filename)])
except Exception as e:
raise ValueError(f"Failed to install {filename}") from e
def _install_isaac_sim_package(package: str, temp_dir: Path):
package_name = package.split("-")[0].replace("_", "-")
filename = _get_filename(package, temp_dir)
url = f"{BASE_URL}/{package_name}/{filename}"
try:
_download_package(url, filename)
_pip_install(_rename_if_necessary(filename))
except Exception as e:
click.echo(f"Failed to install {package}: {str(e)}")
raise
def _setup_windows_conda_env(isaac_sim_path: Path, conda_prefix: Path):
# Create directories
for dir_name in ["activate.d", "deactivate.d"]:
os.makedirs(conda_prefix / "etc" / "conda" / dir_name, exist_ok=True)
# Create empty files
for file_name in ["env_vars.bat", "env_vars.ps1"]:
for dir_name in ["activate.d", "deactivate.d"]:
(conda_prefix / "etc" / "conda" / dir_name / file_name).touch()
# Setup CMD activation script
cmd_act_file = conda_prefix / "etc" / "conda" / "activate.d" / "env_vars.bat"
with cmd_act_file.open("w") as f:
f.write("@echo off\n")
f.write("set PYTHONPATH_OLD=%PYTHONPATH%\n")
f.write(f"set PYTHONPATH=%PYTHONPATH%;{isaac_sim_path}\\site\n")
f.write(f"set CARB_APP_PATH={isaac_sim_path}\\kit\n")
f.write(f"set EXP_PATH={isaac_sim_path}\\apps\n")
f.write(f"set ISAAC_PATH={isaac_sim_path}\n")
# Setup CMD deactivation script
cmd_deact_file = conda_prefix / "etc" / "conda" / "deactivate.d" / "env_vars.bat"
with cmd_deact_file.open("w") as f:
f.write("@echo off\n")
f.write("set PYTHONPATH=%PYTHONPATH_OLD%\n")
f.write('set PYTHONPATH_OLD=""\n')
# Setup PowerShell activation script
ps_act_file = conda_prefix / "etc" / "conda" / "activate.d" / "env_vars.ps1"
with ps_act_file.open("w") as f:
f.write('$env:PYTHONPATH_OLD="$env:PYTHONPATH"\n')
f.write(f'$env:PYTHONPATH="$env:PYTHONPATH;{isaac_sim_path}\\site"\n')
f.write(f'$env:CARB_APP_PATH="{isaac_sim_path}\\kit"\n')
f.write(f'$env:EXP_PATH="{isaac_sim_path}\\apps"\n')
f.write(f'$env:ISAAC_PATH="{isaac_sim_path}"\n')
# Setup PowerShell deactivation script
ps_deact_file = conda_prefix / "etc" / "conda" / "deactivate.d" / "env_vars.ps1"
with ps_deact_file.open("w") as f:
f.write('$env:PYTHONPATH="$env:PYTHONPATH_OLD"\n')
f.write('$env:PYTHONPATH_OLD="$null"\n')
def _setup_unix_conda_env(isaac_sim_path: Path, conda_prefix: Path):
# Set up conda environment files
for dir_name in ["activate.d", "deactivate.d"]:
os.makedirs(conda_prefix / "etc" / "conda" / dir_name, exist_ok=True)
# Create activation script
with open(conda_prefix / "etc" / "conda" / "activate.d" / "env_vars.sh", "w") as f:
f.write("#!/bin/sh\n")
f.write("export LD_LIBRARY_PATH_OLD=$LD_LIBRARY_PATH\n")
f.write("export PYTHONPATH_OLD=$PYTHONPATH\n")
f.write(f"source {isaac_sim_path}/setup_conda_env.sh\n")
# Create deactivation script
with open(conda_prefix / "etc" / "conda" / "deactivate.d" / "env_vars.sh", "w") as f:
f.write("#!/bin/sh\n")
f.write("export LD_LIBRARY_PATH=$LD_LIBRARY_PATH_OLD\n")
f.write("export PYTHONPATH=$PYTHONPATH_OLD\n")
f.write("unset ISAAC_PATH\n")
f.write("unset CARB_APP_PATH\n")
f.write("unset LD_LIBRARY_PATH_OLD\n")
f.write("unset PYTHONPATH_OLD\n")
def _launcher_based_install(isaac_sim_path: Optional[Path]):
# If we are using a launcher-based installation, we need to find the path to the Isaac Sim installation
if isaac_sim_path is None:
isaac_sim_path = _find_isaac_sim_path()
# If it's not at the provided or default path, remove it
if isaac_sim_path is None or not list(Path(isaac_sim_path).glob("isaac*.*")):
return False
# Update conda environment files to point to the specified Isaac Sim installation
conda_prefix = Path(os.environ["CONDA_PREFIX"])
if platform.system() == "Windows":
_setup_windows_conda_env(isaac_sim_path, conda_prefix)
else:
_setup_unix_conda_env(isaac_sim_path, conda_prefix)
return True
def _pip_based_install():
try:
# Create a temporary directory to download the packages
with tempfile.TemporaryDirectory() as temp_dir:
# Install all required packages
for package in ISAAC_SIM_PACKAGES:
_install_isaac_sim_package(package, temp_dir)
# Check that it can now be imported
import isaacsim
except ImportError:
return False
return True
def attempt_launcher_install(isaac_sim_path: Optional[Path]):
click.echo("Checking for an existing launcher-based Isaac Sim installation...")
success = _launcher_based_install(isaac_sim_path)
if success:
click.echo("Successfully found and attached to launcher-based Isaac Sim installation.")
else:
click.echo("We did not find Isaac Sim installed via the launcher.")
return success
def attempt_pip_install():
click.echo("We will now try to install Isaac Sim via pip.")
success = _pip_based_install()
if success:
click.echo("Successfully installed Isaac Sim via pip.")
else:
click.echo("Failed to import isaacsim. Something went wrong during the pip installation.")
return success
@click.command()
@click.option(
"--install-datasets", default=True, help="Install the OmniGibson dataset and assets after installing Isaac Sim"
)
@click.option(
"--force-pip-install",
default=False,
help="Install Isaac Sim via pip even if a launcher-based installation is found",
)
@click.option(
"--force-launcher-install",
default=False,
help="Do not install Isaac Sim via pip even if a launcher-based installation is not found",
)
@click.option(
"--isaac-sim-path",
type=click.Path(exists=True, dir_okay=True, file_okay=False, writeable=True, readable=True, path_type=Path),
default=None,
help="Path to the existing launcher-based Isaac Sim installation directory, to force the setup script to use it",
)
def setup_omnigibson(
install_datasets: bool, force_pip_install: bool, force_launcher_install: bool, isaac_sim_path: Optional[Path]
):
if force_pip_install and force_launcher_install:
click.echo("You can't force both pip and launcher-based installations at the same time.")
return
# Check that we are in a conda environment
if "CONDA_PREFIX" not in os.environ:
click.echo("Please run this script from within a conda environment.")
click.echo("You can create one by running `conda create -n omnigibson python=3.10`.")
return
# Check that the current interpreter is Python 3.10
if sys.version_info[:2] != (3, 10):
click.echo("Please run this script with Python 3.10.")
return
# First, try to install Isaac Sim via the launcher
installation_successful = False
if not force_pip_install:
installation_successful = attempt_launcher_install(isaac_sim_path)
# If that failed, try to install it via pip
if not installation_successful:
if force_launcher_install:
# If the user forced a launcher-based installation, we should not try to install via pip
click.echo("You forced the script to use a launcher-based installation, but we couldn't find it.")
click.echo("Please make sure you have installed Isaac Sim correctly before running this setup script.")
else:
installation_successful = attempt_pip_install()
# If neither installation was successful, we should exit
if not installation_successful:
click.echo("Failed to install Isaac Sim. Please check the installation requirements and try again.")
return
# Now prompt the user to install the dataset and assets
click.echo("Isaac Sim has been successfully installed.")
if install_datasets:
click.echo("We will now install the datasets.")
# Only execute if the dataset path or asset path does not exist
dataset_exists, assets_exist = os.path.exists(gm.DATASET_PATH), os.path.exists(gm.ASSET_PATH)
if not (dataset_exists and assets_exist):
# Ask user which dataset to install
click.echo(f"OmniGibson will now install data under the following locations:")
click.echo(f" dataset (~25GB): {gm.DATASET_PATH}")
click.echo(f" assets (~2.5GB): {gm.ASSET_PATH}")
click.echo(
f"If you want to install data under a different path, please change the DATA_PATH variable in omnigibson/macros.py and "
f"rerun omnigibson/download_datasets.py."
)
if click.confirm("Do you want to continue?", default=True):
# Only download if the dataset path doesn't exist
if not dataset_exists:
click.echo("Downloading dataset...")
download_og_dataset()
# Only download if the asset path doesn't exist
if not assets_exist:
click.echo("Downloading assets...")
download_assets()
else:
click.echo(
"You chose not to install dataset for now. You can install it later by running python omnigibson/download_datasets.py."
)
click.echo(
"\nOmniGibson setup completed! You can now run your experiments. "
"Visit https://behavior.stanford.edu/omnigibson/getting_started/examples.html for some examples, "
"and https://behavior.stanford.edu/omnigibson-develop/getting_started/quickstart.html for a quickstart "
"guide for working with OmniGibson APIs."
)
if __name__ == "__main__":
setup_omnigibson()

View File

@ -1,92 +0,0 @@
@echo off
:: Make sure that the ISAAC_SIM_PATH variable is set correctly
dir /b /o:-n %userprofile%\AppData\Local\ov\pkg\isaac_sim* > NUL
if errorlevel 0 (
for /f "tokens=* usebackq" %%f in (`dir /b /o:n %userprofile%\AppData\Local\ov\pkg\isaac_sim*`) do set ISAAC_SIM_PATH=%userprofile%\AppData\Local\ov\pkg\%%f
setlocal enabledelayedexpansion
echo We found Isaac Sim installed at !ISAAC_SIM_PATH!. OmniGibson will use it by default.
endlocal
set /p ISAAC_SIM_PATH=If you want to use a different one, please type in the path containing isaac-sim.bat here ^(press enter to skip^) ^>^>^>
) else (
echo We did not find Isaac Sim under %userprofile%\AppData\Local\ov\pkg.
echo If you haven't installed Isaac Sim yet, please do so before running this setup script.
set /p ISAAC_SIM_PATH=If you have already installed it in a custom location, please type in the path containing isaac-sim.bat here ^>^>^>
)
:check_isaac_sim_path
if not exist %ISAAC_SIM_PATH%\isaac*.bat (
set /p ISAAC_SIM_PATH=isaac*.bat not found in %ISAAC_SIM_PATH%! Make sure you have entered the correct path ^>^>^>
goto :check_isaac_sim_path
)
echo:
echo Using Isaac Sim at %ISAAC_SIM_PATH%
echo:
:: Choose venv name
set conda_name=omnigibson
echo The new conda environment will be named omnigibson by default.
set /p conda_name=If you want to use a different name, please type in here ^(press enter to skip^) ^>^>^>
echo:
echo Using %conda_name% as the conda environment name
echo:
:: Get Python version from Isaac Sim
FOR /F "tokens=*" %%g IN ('%ISAAC_SIM_PATH%\python.bat -c "import platform; print(platform.python_version())"') do (SET ISAAC_PYTHON_VERSION=%%g)
echo Using Python version %ISAAC_PYTHON_VERSION% matching your current Isaac Sim version
:: Create a conda environment with the appropriate python version
call conda create -y -n %conda_name% python=%ISAAC_PYTHON_VERSION% || goto :error
call conda activate %conda_name% || goto :error
:: We add some preprocessing information so that the Isaac Sim paths are linked to this environment upon startup
:: See https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html#macos-and-linux for reference
mkdir %CONDA_PREFIX%\etc\conda\activate.d
mkdir %CONDA_PREFIX%\etc\conda\deactivate.d
type NUL>%CONDA_PREFIX%\etc\conda\activate.d\env_vars.bat
type NUL>%CONDA_PREFIX%\etc\conda\deactivate.d\env_vars.bat
type NUL>%CONDA_PREFIX%\etc\conda\activate.d\env_vars.ps1
type NUL>%CONDA_PREFIX%\etc\conda\deactivate.d\env_vars.ps1
:: Add support for cmd
set CONDA_ACT_FILE_CMD=%CONDA_PREFIX%\etc\conda\activate.d\env_vars.bat
echo @echo off>>%CONDA_ACT_FILE_CMD%
echo set PYTHONPATH_OLD=%%PYTHONPATH%%>>%CONDA_ACT_FILE_CMD%
echo set PYTHONPATH=%%PYTHONPATH%%;%ISAAC_SIM_PATH%\site>>%CONDA_ACT_FILE_CMD%
echo set CARB_APP_PATH=%ISAAC_SIM_PATH%\kit>>%CONDA_ACT_FILE_CMD%
echo set EXP_PATH=%ISAAC_SIM_PATH%\apps>>%CONDA_ACT_FILE_CMD%
echo set ISAAC_PATH=%ISAAC_SIM_PATH%>>%CONDA_ACT_FILE_CMD%
set CONDA_DEACT_FILE_CMD=%CONDA_PREFIX%\etc\conda\deactivate.d\env_vars.bat
echo @echo off>>%CONDA_DEACT_FILE_CMD%
echo set PYTHONPATH=%%PYTHONPATH_OLD%%>>%CONDA_DEACT_FILE_CMD%
echo set PYTHONPATH_OLD="">>%CONDA_DEACT_FILE_CMD%
:: Add support for powershell
set CONDA_ACT_FILE_PWSH=%CONDA_PREFIX%\etc\conda\activate.d\env_vars.ps1
echo $env:PYTHONPATH_OLD="$env:PYTHONPATH">>%CONDA_ACT_FILE_PWSH%
echo $env:PYTHONPATH="$env:PYTHONPATH;%ISAAC_SIM_PATH%\site">>%CONDA_ACT_FILE_PWSH%
echo $env:CARB_APP_PATH="%ISAAC_SIM_PATH%\kit">>%CONDA_ACT_FILE_PWSH%
echo $env:EXP_PATH="%ISAAC_SIM_PATH%\apps">>%CONDA_ACT_FILE_PWSH%
echo $env:ISAAC_PATH="%ISAAC_SIM_PATH%">>%CONDA_ACT_FILE_PWSH%
set CONDA_DEACT_FILE_PWSH=%CONDA_PREFIX%\etc\conda\deactivate.d\env_vars.ps1
echo $env:PYTHONPATH="$env:PYTHONPATH_OLD">>%CONDA_DEACT_FILE_PWSH%
echo $env:PYTHONPATH_OLD="$null">>%CONDA_DEACT_FILE_PWSH%
:: Install omnigibson!
call pip install -e . || goto :error
:: Cycle conda environment so that all dependencies are propagated
call conda deactivate || goto :error
goto :end
:error
echo:
echo An error occurred during installation. Please check the error message above.
echo:
exit /b
:end
echo:
echo OmniGibson successfully installed! Please run conda activate %conda_name% to activate the environment.
echo:

View File

@ -1,68 +0,0 @@
#!/usr/bin/env bash
set -eo &> /dev/null
# Make sure that the ISAAC_SIM_PATH variable is set correctly
if [[ -d ~/.local/share/ov/pkg ]] && [[ $(ls ~/.local/share/ov/pkg | grep isaac) ]];
then
FOUND_ISAAC_SIM_PATH=$(ls -d ~/.local/share/ov/pkg/* | grep isaac | tail -n 1)
echo "We found Isaac Sim installed at $FOUND_ISAAC_SIM_PATH. OmniGibson will use it by default."
read -p "If you want to use a different one, please type in the path containing isaac-sim.sh here (press enter to skip) >>> " ISAAC_SIM_PATH
ISAAC_SIM_PATH=${ISAAC_SIM_PATH:-$FOUND_ISAAC_SIM_PATH}
else
echo "We did not find Isaac Sim under ~/.local/share/ov/pkg."
echo "If you haven't installed Isaac Sim yet, please do so before running this setup script."
read -p "If you have already installed it in a custom location, please type in the path containing isaac-sim.sh here >>> " ISAAC_SIM_PATH
fi
while [[ ! -n $(find "${ISAAC_SIM_PATH}" -maxdepth 1 -name "isaac*.sh" 2>/dev/null) ]]; do
read -p "isaac*.sh not found in $ISAAC_SIM_PATH! Make sure you have entered the correct path >>> " ISAAC_SIM_PATH
done
echo -e "\nUsing Isaac Sim at $ISAAC_SIM_PATH\n"
# Choose venv name
echo "The new conda environment will be named omnigibson by default."
read -p "If you want to use a different name, please type in here (press enter to skip) >>> " conda_name
conda_name=${conda_name:-omnigibson}
echo -e "\nUsing $conda_name as the conda environment name\n"
# Get Python version from Isaac Sim
ISAAC_PYTHON_VERSION=$(${ISAAC_SIM_PATH}/python.sh -c "import platform; print(platform.python_version())")
ISAAC_PYTHON_VERSION="${ISAAC_PYTHON_VERSION##*$'\n'}" # get rid of conda activation warnings
echo Using Python version $ISAAC_PYTHON_VERSION matching your current Isaac Sim version
# Create a conda environment with the appropriate python version
source $(conda info --base)/etc/profile.d/conda.sh
conda create -y -n $conda_name python=${ISAAC_PYTHON_VERSION}
# Now activate the omnigibson environment
conda activate $conda_name
mkdir -p ${CONDA_PREFIX}/etc/conda/activate.d
mkdir -p ${CONDA_PREFIX}/etc/conda/deactivate.d
touch ${CONDA_PREFIX}/etc/conda/activate.d/env_vars.sh
touch ${CONDA_PREFIX}/etc/conda/deactivate.d/env_vars.sh
# We add some preprocessing information so that the Isaac Sim paths are linked to this environment upon startup
# See https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html#macos-and-linux for reference
CONDA_ACT_FILE="${CONDA_PREFIX}/etc/conda/activate.d/env_vars.sh"
echo '#!/bin/sh' > ${CONDA_ACT_FILE}
echo "export LD_LIBRARY_PATH_OLD=\$LD_LIBRARY_PATH" >> ${CONDA_ACT_FILE}
echo "export PYTHONPATH_OLD=\$PYTHONPATH" >> ${CONDA_ACT_FILE}
echo "source ${ISAAC_SIM_PATH}/setup_conda_env.sh" >> ${CONDA_ACT_FILE}
CONDA_DEACT_FILE="${CONDA_PREFIX}/etc/conda/deactivate.d/env_vars.sh"
echo '#!/bin/sh' > ${CONDA_DEACT_FILE}
echo "export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH_OLD" >> ${CONDA_DEACT_FILE}
echo "export PYTHONPATH=\$PYTHONPATH_OLD" >> ${CONDA_DEACT_FILE}
echo "unset ISAAC_PATH" >> ${CONDA_DEACT_FILE}
echo "unset CARB_APP_PATH" >> ${CONDA_DEACT_FILE}
echo "unset LD_LIBRARY_PATH_OLD" >> ${CONDA_DEACT_FILE}
echo "unset PYTHONPATH_OLD" >> ${CONDA_DEACT_FILE}
# Install omnigibson!
pip install -e .
# Cycle conda environment so that all dependencies are propagated
conda deactivate
echo -e "\nOmniGibson successfully installed! Please run conda activate $conda_name to activate the environment.\n"