Full Code of robotology/gym-ignition for AI

master 4bc8e0465eed cached
245 files
1.2 MB
314.1k tokens
679 symbols
1 requests
Download .txt
Showing preview only (1,332K chars total). Download the full file or copy to clipboard to get everything.
Repository: robotology/gym-ignition
Branch: master
Commit: 4bc8e0465eed
Files: 245
Total size: 1.2 MB

Directory structure:
gitextract_2yu_wlwv/

├── .clang-format
├── .docker/
│   ├── Dockerfile
│   ├── base.Dockerfile
│   ├── cicd-devel.Dockerfile
│   ├── cicd-master.Dockerfile
│   ├── docker-compose.yml
│   ├── entrypoint.sh
│   └── setup_virtualenv.sh
├── .github/
│   ├── CODEOWNERS
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── release.yml
│   └── workflows/
│       ├── cicd.yml
│       ├── docker.yml
│       └── style.yml
├── .gitignore
├── CMakeLists.txt
├── LICENSE
├── README.md
├── docs/
│   ├── CMakeLists.txt
│   ├── doxygen/
│   │   └── CMakeLists.txt
│   └── sphinx/
│       ├── CMakeLists.txt
│       ├── _templates/
│       │   ├── module.rst_t
│       │   ├── package.rst_t
│       │   ├── toc.rst_t
│       │   ├── versioning.html
│       │   └── versions.html
│       ├── apidoc/
│       │   ├── gym-ignition/
│       │   │   ├── gym_ignition.base.rst
│       │   │   ├── gym_ignition.context.gazebo.rst
│       │   │   ├── gym_ignition.context.rst
│       │   │   ├── gym_ignition.randomizers.model.rst
│       │   │   ├── gym_ignition.randomizers.physics.rst
│       │   │   ├── gym_ignition.randomizers.rst
│       │   │   ├── gym_ignition.rbd.idyntree.rst
│       │   │   ├── gym_ignition.rbd.rst
│       │   │   ├── gym_ignition.rst
│       │   │   ├── gym_ignition.runtimes.rst
│       │   │   ├── gym_ignition.scenario.rst
│       │   │   └── gym_ignition.utils.rst
│       │   ├── gym-ignition-environments/
│       │   │   ├── gym_ignition_environments.models.rst
│       │   │   ├── gym_ignition_environments.randomizers.rst
│       │   │   ├── gym_ignition_environments.rst
│       │   │   └── gym_ignition_environments.tasks.rst
│       │   └── scenario/
│       │       ├── scenario.bindings.rst
│       │       └── scenario.rst
│       ├── breathe/
│       │   ├── core.rst
│       │   └── gazebo.rst
│       ├── conf.py
│       ├── getting_started/
│       │   ├── gym-ignition.rst
│       │   ├── manipulation.rst
│       │   └── scenario.rst
│       ├── index.html
│       ├── index.rst
│       ├── info/
│       │   ├── faq.rst
│       │   └── limitations.rst
│       ├── installation/
│       │   ├── developer.rst
│       │   ├── nightly.rst
│       │   ├── stable.rst
│       │   ├── support_policy.rst
│       │   ├── system_configuration.rst
│       │   └── virtual_environment.rst
│       ├── what/
│       │   ├── what_is_gym_ignition.rst
│       │   └── what_is_scenario.rst
│       └── why/
│           ├── motivations.rst
│           ├── why_gym_ignition.rst
│           ├── why_ignition_gazebo.rst
│           └── why_scenario.rst
├── examples/
│   ├── panda_pick_and_place.py
│   └── python/
│       └── launch_cartpole.py
├── pyproject.toml
├── python/
│   ├── gym_ignition/
│   │   ├── __init__.py
│   │   ├── base/
│   │   │   ├── __init__.py
│   │   │   ├── runtime.py
│   │   │   └── task.py
│   │   ├── context/
│   │   │   ├── __init__.py
│   │   │   └── gazebo/
│   │   │       ├── __init__.py
│   │   │       ├── controllers.py
│   │   │       └── plugin.py
│   │   ├── randomizers/
│   │   │   ├── __init__.py
│   │   │   ├── abc.py
│   │   │   ├── gazebo_env_randomizer.py
│   │   │   ├── model/
│   │   │   │   ├── __init__.py
│   │   │   │   └── sdf.py
│   │   │   └── physics/
│   │   │       ├── __init__.py
│   │   │       └── dart.py
│   │   ├── rbd/
│   │   │   ├── __init__.py
│   │   │   ├── conversions.py
│   │   │   ├── idyntree/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── helpers.py
│   │   │   │   ├── inverse_kinematics_nlp.py
│   │   │   │   ├── kindyncomputations.py
│   │   │   │   └── numpy.py
│   │   │   └── utils.py
│   │   ├── runtimes/
│   │   │   ├── __init__.py
│   │   │   ├── gazebo_runtime.py
│   │   │   └── realtime_runtime.py
│   │   ├── scenario/
│   │   │   ├── __init__.py
│   │   │   ├── model_with_file.py
│   │   │   └── model_wrapper.py
│   │   └── utils/
│   │       ├── __init__.py
│   │       ├── logger.py
│   │       ├── math.py
│   │       ├── misc.py
│   │       ├── resource_finder.py
│   │       ├── scenario.py
│   │       └── typing.py
│   └── gym_ignition_environments/
│       ├── __init__.py
│       ├── models/
│       │   ├── __init__.py
│       │   ├── cartpole.py
│       │   ├── icub.py
│       │   ├── panda.py
│       │   └── pendulum.py
│       ├── randomizers/
│       │   ├── __init__.py
│       │   ├── cartpole.py
│       │   └── cartpole_no_rand.py
│       └── tasks/
│           ├── __init__.py
│           ├── cartpole_continuous_balancing.py
│           ├── cartpole_continuous_swingup.py
│           ├── cartpole_discrete_balancing.py
│           └── pendulum_swingup.py
├── scenario/
│   ├── CMakeLists.txt
│   ├── README.md
│   ├── bindings/
│   │   ├── CMakeLists.txt
│   │   ├── __init__.py
│   │   ├── core/
│   │   │   ├── CMakeLists.txt
│   │   │   └── core.i
│   │   └── gazebo/
│   │       ├── CMakeLists.txt
│   │       ├── gazebo.i
│   │       └── to_gazebo.i
│   ├── cmake/
│   │   ├── AddUninstallTarget.cmake
│   │   ├── AliasImportedTarget.cmake
│   │   ├── FindIgnitionDistribution.cmake
│   │   ├── FindPackageHandleStandardArgs.cmake
│   │   ├── FindPackageMessage.cmake
│   │   ├── FindPython/
│   │   │   └── Support.cmake
│   │   ├── FindPython3.cmake
│   │   ├── FindSphinx.cmake
│   │   ├── FindSphinxApidoc.cmake
│   │   ├── FindSphinxMultiVersion.cmake
│   │   ├── ImportTargetsCitadel.cmake
│   │   ├── ImportTargetsDome.cmake
│   │   ├── ImportTargetsEdifice.cmake
│   │   └── ImportTargetsFortress.cmake
│   ├── deps/
│   │   ├── CMakeLists.txt
│   │   └── clara/
│   │       └── clara.hpp
│   ├── pyproject.toml
│   ├── setup.cfg
│   ├── setup.py
│   └── src/
│       ├── CMakeLists.txt
│       ├── controllers/
│       │   ├── CMakeLists.txt
│       │   ├── include/
│       │   │   └── scenario/
│       │   │       └── controllers/
│       │   │           ├── ComputedTorqueFixedBase.h
│       │   │           ├── Controller.h
│       │   │           └── References.h
│       │   └── src/
│       │       └── ComputedTorqueFixedBase.cpp
│       ├── core/
│       │   ├── CMakeLists.txt
│       │   ├── include/
│       │   │   └── scenario/
│       │   │       └── core/
│       │   │           ├── Joint.h
│       │   │           ├── Link.h
│       │   │           ├── Model.h
│       │   │           ├── World.h
│       │   │           └── utils/
│       │   │               ├── Log.h
│       │   │               ├── signals.h
│       │   │               └── utils.h
│       │   └── src/
│       │       ├── signals.cpp
│       │       └── utils.cpp
│       ├── gazebo/
│       │   ├── CMakeLists.txt
│       │   ├── include/
│       │   │   └── scenario/
│       │   │       └── gazebo/
│       │   │           ├── GazeboEntity.h
│       │   │           ├── GazeboSimulator.h
│       │   │           ├── Joint.h
│       │   │           ├── Link.h
│       │   │           ├── Log.h
│       │   │           ├── Model.h
│       │   │           ├── World.h
│       │   │           ├── components/
│       │   │           │   ├── BasePoseTarget.h
│       │   │           │   ├── BaseWorldAccelerationTarget.h
│       │   │           │   ├── BaseWorldVelocityTarget.h
│       │   │           │   ├── ExternalWorldWrenchCmdWithDuration.h
│       │   │           │   ├── HistoryOfAppliedJointForces.h
│       │   │           │   ├── JointAcceleration.h
│       │   │           │   ├── JointAccelerationTarget.h
│       │   │           │   ├── JointControlMode.h
│       │   │           │   ├── JointController.h
│       │   │           │   ├── JointControllerPeriod.h
│       │   │           │   ├── JointPID.h
│       │   │           │   ├── JointPositionTarget.h
│       │   │           │   ├── JointVelocityTarget.h
│       │   │           │   ├── SimulatedTime.h
│       │   │           │   └── Timestamp.h
│       │   │           ├── exceptions.h
│       │   │           ├── helpers.h
│       │   │           └── utils.h
│       │   └── src/
│       │       ├── GazeboSimulator.cpp
│       │       ├── Joint.cpp
│       │       ├── Link.cpp
│       │       ├── Model.cpp
│       │       ├── World.cpp
│       │       ├── helpers.cpp
│       │       └── utils.cpp
│       └── plugins/
│           ├── CMakeLists.txt
│           ├── ControllerRunner/
│           │   ├── CMakeLists.txt
│           │   ├── ControllerRunner.cpp
│           │   ├── ControllerRunner.h
│           │   ├── ControllersFactory.cpp
│           │   └── ControllersFactory.h
│           ├── JointController/
│           │   ├── CMakeLists.txt
│           │   ├── JointController.cpp
│           │   └── JointController.h
│           └── Physics/
│               ├── CMakeLists.txt
│               ├── CanonicalLinkModelTracker.hh
│               ├── EntityFeatureMap.hh
│               ├── Physics.cc
│               └── Physics.hh
├── setup.cfg
├── setup.py
└── tests/
    ├── .python/
    │   ├── __init__.py
    │   ├── test_contacts.py
    │   ├── test_environments_gazebowrapper.py
    │   ├── test_externalforce.py
    │   ├── test_joint_force.py
    │   ├── test_pendulum_wrt_ground_truth.py
    │   ├── test_rates.py
    │   ├── test_robot_base.py
    │   ├── test_robot_controller.py
    │   ├── test_runtimes.py
    │   └── utils.py
    ├── __init__.py
    ├── assets/
    │   └── worlds/
    │       └── fuel_support.sdf
    ├── common/
    │   ├── __init__.py
    │   └── utils.py
    ├── test_gym_ignition/
    │   ├── __init__.py
    │   ├── test_inverse_kinematics.py
    │   ├── test_normalization.py
    │   ├── test_reproducibility.py
    │   └── test_sdf_randomizer.py
    └── test_scenario/
        ├── __init__.py
        ├── test_contacts.py
        ├── test_custom_controllers.py
        ├── test_external_wrench.py
        ├── test_gazebo_simulator.py
        ├── test_ignition_fuel.py
        ├── test_link_velocities.py
        ├── test_model.py
        ├── test_multi_world.py
        ├── test_pid_controllers.py
        ├── test_velocity_direct.py
        └── test_world.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .clang-format
================================================
---
Language:        Cpp
# BasedOnStyle:  WebKit
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands:   true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
  AfterClass:      true
  AfterControlStatement: false
  AfterEnum:       true
  AfterFunction:   true
  AfterNamespace:  false
  AfterObjCDeclaration: false
  AfterStruct:     true
  AfterUnion:      false
  BeforeCatch:     true
  BeforeElse:      true
  IndentBraces:    false
  SplitEmptyFunction: false
  SplitEmptyRecord: false
  SplitEmptyNamespace: false
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: true
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: true
BreakConstructorInitializers: BeforeComma
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit:   80
CommentPragmas:  '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat:   false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
  - foreach
  - Q_FOREACH
  - BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
  - Regex:           '^"(llvm|llvm-c|clang|clang-c)/'
    Priority:        2
  - Regex:           '^(<|"(gtest|gmock|isl|json)/)'
    Priority:        3
  - Regex:           '.*'
    Priority:        1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: true
IndentWidth:     4
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd:   ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
ReflowComments:  true
SortIncludes:    true
SortUsingDeclarations: true
SpaceAfterCStyleCast: true
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles:  false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard:        Cpp11
TabWidth:        4
UseTab:          Never
...


================================================
FILE: .docker/Dockerfile
================================================
ARG from=diegoferigo/gym-ignition:pypi-master
FROM ${from}

# Install the PyPI package in a virtualenv
ARG pip_options=""
RUN virtualenv -p $(which python3) ${VIRTUAL_ENV} &&\
    python -m pip install --upgrade pip &&\
    pip install ${pip_options} gym-ignition &&\
    rm -r $HOME/.cache/pip

# Clone the repository
WORKDIR /github
ARG branch="master"
RUN git clone -b ${branch} https://github.com/robotology/gym-ignition /github

# Reset the entrypoint
ENTRYPOINT [""]

CMD ["bash"]


================================================
FILE: .docker/base.Dockerfile
================================================
ARG from=ubuntu:focal
FROM ${from}

SHELL ["/bin/bash", "-c"]

# Setup locales and timezone
ARG TZ=Europe/Rome
ARG DEBIAN_FRONTEND=noninteractive
RUN rm -f /etc/localtime &&\
    ln -s /usr/share/zoneinfo/"${TZ}" /etc/localtime &&\
    apt-get update &&\
    apt-get install -y --no-install-recommends locales locales-all tzdata &&\
    rm -rf /var/lib/apt/lists/*

# Install tools and toolchain
RUN apt-get update &&\
    apt-get install -y --no-install-recommends \
        wget \
        software-properties-common \
        apt-transport-https \
        apt-utils \
        gnupg2 \
        nano \
        rename \
        source-highlight \
        &&\
    wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | apt-key add - && \
    apt-add-repository "deb https://apt.kitware.com/ubuntu/ `lsb_release -cs` main" &&\
    add-apt-repository ppa:deadsnakes/ppa &&\
    wget -nv -O - http://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - &&\
    apt-add-repository -y "deb http://apt.llvm.org/`lsb_release -cs`/ llvm-toolchain-`lsb_release -cs`-10 main" &&\
    apt-get update &&\
    apt-get install -y --no-install-recommends \
        build-essential \
        clang-10 \
        git \
        cmake \
        cmake-curses-gui \
        ninja-build \
        valgrind \
        libgflags-dev \
        python3-pip \
        python3-wheel \
        python3.8 \
        python3.8-dev \
        libpython3.8-dev \
        virtualenv \
        swig \
        &&\
    rm -rf /var/lib/apt/lists/*

# Update git (required by actions/checkout)
RUN add-apt-repository ppa:git-core/ppa &&\
    apt-get update &&\
    apt-get install -y --no-install-recommends git &&\
    rm -rf /var/lib/apt/lists/*

# Common virtualenv properties
ENV VIRTUAL_ENV=/venv
ENV PATH=$VIRTUAL_ENV/bin:$PATH

CMD ["bash"]


================================================
FILE: .docker/cicd-devel.Dockerfile
================================================
ARG from=diegoferigo/gym-ignition:base
FROM ${from}

RUN pip3 install vcstool colcon-common-extensions &&\
    rm -r $HOME/.cache/pip

ARG CMAKE_BUILD_TYPE="Release"
ARG ignition_codename="fortress"
ARG IGNITION_DEFAULT_CHANNEL="stable"

RUN echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-${IGNITION_DEFAULT_CHANNEL} `lsb_release -cs` main" > \
        /etc/apt/sources.list.d/gazebo-${IGNITION_DEFAULT_CHANNEL}.list &&\
    wget http://packages.osrfoundation.org/gazebo.key -O - | apt-key add - &&\
    apt-get update &&\
    mkdir -p /workspace/src &&\
    cd /workspace/src &&\
    wget https://raw.githubusercontent.com/ignition-tooling/gazebodistro/master/collection-${ignition_codename}.yaml &&\
    vcs import < collection-${ignition_codename}.yaml &&\
    apt -y install --no-install-recommends \
        $(sort -u $(find . -iname 'packages-'$(lsb_release -cs)'.apt' -o -iname 'packages.apt') | grep -v -E "dart|^libignition|^libsdformat" | tr '\n' ' ') &&\
    rm -rf /var/lib/apt/lists/* &&\
    cd /workspace &&\
    colcon graph &&\
    colcon build \
        --cmake-args \
            -GNinja \
            -DBUILD_TESTING:BOOL=OFF \
            -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} \
        --merge-install \
        &&\
    find build/ -type f -not -name 'CMakeCache.txt' -delete &&\
    echo "source /workspace/install/setup.bash" >> /etc/bash.bashrc

# Source /etc/bash.bashrc before each command
SHELL ["/bin/bash", "-i", "-c"]

COPY entrypoint.sh /entrypoint.sh
COPY setup_virtualenv.sh /setup_virtualenv.sh
RUN chmod 755 /entrypoint.sh
RUN chmod 755 /setup_virtualenv.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["bash"]


================================================
FILE: .docker/cicd-master.Dockerfile
================================================
ARG from=diegoferigo/gym-ignition:base
FROM ${from}

# Install ignition gazebo
ARG ignition_codename="fortress"
RUN echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-stable `lsb_release -cs` main" \
        > /etc/apt/sources.list.d/gazebo-stable.list &&\
    wget http://packages.osrfoundation.org/gazebo.key -O - | apt-key add - &&\
    apt-get update &&\
    apt-get install -y --no-install-recommends ignition-${ignition_codename} &&\
    rm -rf /var/lib/apt/lists/*

COPY entrypoint.sh /entrypoint.sh
COPY setup_virtualenv.sh /setup_virtualenv.sh
RUN chmod 755 /entrypoint.sh
RUN chmod 755 /setup_virtualenv.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["bash"]


================================================
FILE: .docker/docker-compose.yml
================================================
version: '3.0'

services:

  base:
    build:
      args:
        from: ubuntu:focal
      context: .
      dockerfile: base.Dockerfile
    image: diegoferigo/gym-ignition:base

  # ======
  # MASTER
  # ======

  ci-master:
    build:
      args:
        from: diegoferigo/gym-ignition:base
        ignition_codename: dome
      context: .
      dockerfile: cicd-master.Dockerfile
    image: diegoferigo/gym-ignition:ci-master

  pypi-master:
    build:
      args:
        from: diegoferigo/gym-ignition:base
        ignition_codename: dome
      context: .
      dockerfile: cicd-master.Dockerfile
    image: diegoferigo/gym-ignition:pypi-master

  # =====
  # DEVEL
  # =====

  ci-devel:
    build:
      args:
        from: diegoferigo/gym-ignition:base
        ignition_codename: fortress
        CMAKE_BUILD_TYPE: Debug
      context: .
      dockerfile: cicd-devel.Dockerfile
    image: diegoferigo/gym-ignition:ci-devel

  pypi-devel:
    build:
      args:
        from: diegoferigo/gym-ignition:base
        ignition_codename: fortress
        CMAKE_BUILD_TYPE: Release
      context: .
      dockerfile: cicd-devel.Dockerfile
    image: diegoferigo/gym-ignition:pypi-devel

  # ====
  # DEMO
  # ====

  latest:
    build:
      args:
        from: diegoferigo/gym-ignition:pypi-master
        branch: master
      context: .
      dockerfile: Dockerfile
    image: diegoferigo/gym-ignition:latest

  nightly:
    build:
      args:
        from: diegoferigo/gym-ignition:ci-devel
        branch: devel
        pip_options: --pre
      context: .
      dockerfile: Dockerfile
    image: diegoferigo/gym-ignition:nightly


================================================
FILE: .docker/entrypoint.sh
================================================
#!/bin/bash
set -e

if [ ! -x "/setup_virtualenv.sh" ] ; then
    echo "File '/setup_virtualenv.sh' not found."
    exit 1
fi

# Setup the python virtualenv
bash /setup_virtualenv.sh

# If a CMD is passed, execute it
exec "$@"


================================================
FILE: .docker/setup_virtualenv.sh
================================================
#!/bin/bash
set -eu

# Read the env variable if exists, otherwise fall back to python3
PYTHON_EXE=python${PYTHON_VERSION:-3}

if [ ! -x $(type -P ${PYTHON_EXE}) ] ; then
    echo "Failed to find ${PYTHON_EXE} in PATH"
    exit 1
fi

# Create an empty virtualenv and enable it by default
virtualenv -p $PYTHON_EXE ${VIRTUAL_ENV}

# Install pytest in the virtual environment
${VIRTUAL_ENV}/bin/pip3 install pytest


================================================
FILE: .github/CODEOWNERS
================================================
# Default owners
*       @diegoferigo


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Report a bug
labels: issue::type::bug
---

<!-- Remove this warning before posting the issue -->

⚠️ If you're not sure whether your problem is a bug, please ask a question in [Discussions][Discussions] instead.

<!-- Make sure you already checked the existing documentation and mark all the checks -->

- [ ] I've read the [FAQ][FAQ]
- [ ] I've read the [Support Policy][Support Policy]
- [ ] I've already searched similar [issues][Issues] and [discussions][Discussions]
- [ ] I've already updated to the most recent supported [release][Releases] (either Stable or Nightly)

[Issues]: https://github.com/robotology/gym-ignition/issues
[Releases]: https://github.com/robotology/gym-ignition/releases
[FAQ]: https://robotology.github.io/gym-ignition/master/info/faq.html
[Discussions]: https://github.com/robotology/gym-ignition/discussions
[Support Policy]: https://robotology.github.io/gym-ignition/master/installation/support_policy.html
    
## Description:

A clear and concise description of the bug and what should be the expected behavior.

## Steps to reproduce

1.
1.
1.

or

```python
# Insert some code
```

## Additional context

<!-- Screenshots, console logs, backtraces, ... -->

<details>
<summary>Title</summary>

Content

</details>

## Environment

- OS: <!-- Insert the distribution, e.g. Ubuntu 20.04 -->
- GPU: <!-- Insert your GPU, e.g. Intel XXX integrated -->    
- Python: <!-- Insert the active Python version and provider, e.g. 3.8.X from virtualenv -->
- Version: <!-- Insert the installed version of gym-ignition and scenario, e.g. v1.2.0 -->
- Channel:
  - [ ] Stable
  - [ ] Nightly
- Installation type:
  - [ ] User
  - [ ] Developer


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Request a new feature
labels: issue::type::enhancement
---

<!-- Remove this warning before posting the issue -->

⚠️ If you're not sure on the specifics of the feature or would like a broader discussion, please consider posting a proposal to [Discussions][Discussions] instead.

[Discussions]: https://github.com/robotology/gym-ignition/discussions

## Summary

Describe what this new feature is about and the context you would find it useful.

## Implementation suggestion

Provide a suggestion on how to implement this feature, which could help us to speed up the implementation.

## Additional context

Screenshots, videos, links, sketches, ...


================================================
FILE: .github/release.yml
================================================
changelog:
  exclude:
    labels:
      - pr::changelog::ignore
    authors: [ ]
  categories:
    - title: Bug fixing and new features
      labels:
        - pr::changelog::bugfix
        - pr::changelog::release
        - pr::changelog::feature
    - title: Documentation, CI/CD, tests
      labels:
        - pr::changelog::docs
        - pr::changelog::cicd
        - pr::changelog::tests
    - title: Other changes
      labels:
        - pr::changelog::other
    - title: No category
      labels: [ "*" ]


================================================
FILE: .github/workflows/cicd.yml
================================================
name: CI/CD

on:
  push:
    branches: ["**"]
    tags-ignore: ["**"]
  pull_request:
  workflow_dispatch:
  release:
    types: [published]

jobs:

# =============
  build-colcon:
# =============
    name: 'colcon@${{ matrix.ignition }}'
    if: |
      (github.event_name == 'push' && github.ref != 'refs/heads/master') ||
      (github.event_name == 'pull_request' && github.event.pull_request.base.ref != 'master')
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        ignition:
          # - dome
          # - edifice
          - fortress
    env:
      CCACHE_DIR: ${{ github.workspace }}/.ccache
    steps:

      - name: '🔍️ Inspect Environment'
        run: |
          env | grep ^GITHUB
          echo ""
          cat ${GITHUB_EVENT_PATH}
          echo ""
          env

      - name: '⬇️️ Install dependencies'
        run: |
          sudo apt-get update
          sudo apt-get install -y --no-install-recommends \
            lz4 \
            git \
            wget \
            gpg-agent \
            ninja-build \
            build-essential \
            software-properties-common

      - name: '🐍 Initialize Python'
        uses: actions/setup-python@v2
        with:
          python-version: 3.8

      - name: '🚚 Compilation cache'
        uses: actions/cache@v2
        with:
          path: ${{ env.CCACHE_DIR }}
          # We include the commit sha in the cache key, as new cache entries are
          # only created if there is no existing entry for the key yet.
          key: ${{ runner.os }}-ccache-${{ matrix.ignition }}-${{ github.sha }}
          # Restore any ccache cache entry, if none for the key above exists
          restore-keys: ${{ runner.os }}-ccache-${{ matrix.ignition }}

      - name: '🚚 Enable ccache'
        run: |
          sudo apt-get update
          sudo apt-get install -y ccache
          echo "/usr/lib/ccache" >> $GITHUB_PATH
          ccache --set-config=max_size=5.0G
          ccache --set-config=sloppiness=file_macro,locale,time_macros
          ccache -p
          ccache -s

      - name: '⚙️ Add osrf ppa'
        run: |
          sudo sh -c 'echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-stable `lsb_release -cs` main" >\
            /etc/apt/sources.list.d/gazebo-stable.list'
          wget http://packages.osrfoundation.org/gazebo.key -O - | sudo apt-key add -
          sudo apt-get update

      - name: '⚙️ Prepare colcon workspace'
        run: |
          pip install vcstool colcon-common-extensions
          sudo mkdir -p /workspace/src /workspace/install
          sudo chmod -R a+rw /workspace
          cd /workspace/src
          wget -O - ${TAGS_YAML} | vcs import
          echo $(sort -u $(find . -iname 'packages-'$(lsb_release -cs)'.apt' -o -iname 'packages.apt') | grep -v -E "^libignition|^libsdformat" | tr '\n' ' ') \
            > /workspace/install/pkg.txt
          xargs -a /workspace/install/pkg.txt sudo apt-get install -y --no-install-recommends
        env:
          TAGS_YAML: https://raw.githubusercontent.com/ignition-tooling/gazebodistro/master/collection-${{ matrix.ignition }}.yaml

      - name: '🏗️ Build colcon workspace'
        run: |
          cd /workspace
          colcon graph
          colcon build \
              --cmake-args \
                  -GNinja \
                  -DBUILD_TESTING:BOOL=OFF \
                  -DCMAKE_BUILD_TYPE=Debug \
              --merge-install

      - name: '📈 Ccache stats'
        run: ccache --show-stats

      - name: '📦️ Compress the workspace'
        run: tar -I lz4 -cf /tmp/workspace_install.tar.lz4 /workspace/install
      - name: '⬆️ Upload the workspace'
        uses: actions/upload-artifact@v2
        with:
          path: /tmp/workspace_install.tar.lz4
          name: workspace-${{ matrix.ignition }}
          retention-days: 1

# ===============
  build-and-test:
# ===============
    name: 'Build and Test [${{matrix.type}}|${{matrix.ignition}}|${{matrix.python}}]'
    if: always()
    needs: [ build-colcon ]
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os:
          - ubuntu-latest
        type:
          - User
          - Developer
        ignition:
          # - dome
          # - edifice
          - fortress
        python:
          - 3.8
          - 3.9
    steps:

      - name: '🔍 Inspect Environment'
        run: |
          env | grep ^GITHUB
          echo ""
          cat ${GITHUB_EVENT_PATH}
          echo ""
          env

      - name: '⬇️ Install build dependencies'
        if: contains(matrix.os, 'ubuntu')
        run: |
          sudo apt-get update
          sudo apt-get install -y --no-install-recommends \
            lz4 \
            git \
            wget \
            cmake \
            gpg-agent \
            ninja-build \
            build-essential \
            software-properties-common

      - name: '🐍 Initialize Python'
        uses: actions/setup-python@v2
        with:
          python-version: ${{ matrix.python }}

      - name: '🔀 Clone repository'
        uses: actions/checkout@master
      - name: '🔀 Download all refs'
        run: git fetch --prune --unshallow

      # ================
      # Install Ignition
      # ================

      - name: '⚙️ Add osrf ppa'
        if: contains(matrix.os, 'ubuntu')
        run: |
          sudo sh -c 'echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-stable `lsb_release -cs` main" >\
            /etc/apt/sources.list.d/gazebo-stable.list'
          wget http://packages.osrfoundation.org/gazebo.key -O - | sudo apt-key add -
          sudo apt-get update
      - name: '[🔒️|stable] Install Ignition from ppa'
        if: |
          contains(matrix.os, 'ubuntu') && (
            github.event_name == 'release' ||
            github.ref == 'refs/heads/master' ||
            (github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'master')
          )
        run: sudo apt-get install -y --no-install-recommends ignition-${{ matrix.ignition }}

      - name: '[🧪|nightly] Download pre-built colcon workspace'
        uses: actions/download-artifact@v2
        if: |
          contains(matrix.os, 'ubuntu') && (
            (github.event_name == 'push' && github.ref != 'refs/heads/master') ||
            (github.event_name == 'pull_request' && github.event.pull_request.base.ref != 'master')
          )
        with:
          path: /tmp
          name: workspace-${{ matrix.ignition }}
      - name: '[🧪|nightly] Setup colcon workspace'
        if: |
          contains(matrix.os, 'ubuntu') && (
            (github.event_name == 'push' && github.ref != 'refs/heads/master') ||
            (github.event_name == 'pull_request' && github.event.pull_request.base.ref != 'master')
          )
        run: |
          sudo tar -I lz4 -xf /tmp/workspace_install.tar.lz4 -C /
          xargs -a /workspace/install/pkg.txt sudo apt-get install -y --no-install-recommends
          echo "source /workspace/install/setup.bash" | sudo tee -a /etc/bash.bashrc

      # =============
      # Build project
      # =============

      # This is required because ScenarIO needs to import the iDynTree targets
      - name: '⬇️ Install iDynTree dependencies'
        if: contains(matrix.os, 'ubuntu')
        run: |
          sudo apt-get update
          sudo apt-get install -y --no-install-recommends \
            libxml2-dev coinor-libipopt-dev libeigen3-dev libassimp-dev swig
      - name: '🤖 Install iDynTree'
        run: |
          pip install idyntree
          IDYNTREE_PYTHON_PKG=$(python3 -c 'import idyntree, pathlib; print(pathlib.Path(idyntree.__file__).parent)')
          echo "CMAKE_PREFIX_PATH=$IDYNTREE_PYTHON_PKG" >> $GITHUB_ENV

      # Note: In order to execute the setup.sh script, the file /etc/bash.bashrc must be sourced.
      #       To do that, we change the shell to a bash interactive session with 'bash -i -e'.

      # Developer installation
      - name: '[👷|developer] Build and Install C++ ScenarIO'
        if: matrix.type == 'Developer'
        shell: bash -i -e {0}
        run: |
          env
          cmake -S . -B build/ \
            -GNinja \
            -DCMAKE_BUILD_TYPE=Debug \
            -DIGNITION_DISTRIBUTION=$(python3 -c "print('${{ matrix.ignition }}'.capitalize())")
          sudo cmake --build build/ --target install
      - name: '[👷|developer] Install Python ScenarIO'
        if: matrix.type == 'Developer'
        run: pip install -e ./scenario

      # User installation
      - name: '[👤|user] Create wheel (default ignition)'
        if: matrix.type == 'User' && matrix.ignition == 'fortress'
        shell: bash -i -e {0}
        run: pip wheel --use-feature=in-tree-build -v -w dist/ ./scenario
      # Note: Calling "pip wheel" with "--global-option" forces all dependencies to be built from their sdist.
      #       Since it's very slow, we create the wheel from setup.py without isolation (requires system deps).
      - name: '[👤|user] Create wheel (custom ignition)'
        if: matrix.type == 'User' && matrix.ignition != 'fortress'
        shell: bash -i -e {0}
        run: |
          pip install wheel setuptools-scm cmake-build-extension
          python3 ./scenario/setup.py bdist_wheel \
            build_ext -DIGNITION_DISTRIBUTION=$(python3 -c "print('${{ matrix.ignition }}'.capitalize())")
      - name: '[👤|user] Install local wheel'
        if: matrix.type == 'User'
        run: pip install -v dist/scenario-*.whl

      - name: '🔍️ Inspect installed ScenarIO package'
        if: matrix.type == 'User' && contains(matrix.os, 'ubuntu')
        run: |
          sudo apt-get install -y --no-install-recommends tree
          tree $(python3 -c "import scenario, pathlib; print(pathlib.Path(scenario.__file__).parent)")

      # ====================
      # Install gym-ignition
      # ====================

      - name: '🐍 Install gym-ignition'
        run: pip install wheel && pip install .[all]

      # ============
      # Test project
      # ============

      - name: '🔍 Inspect installed versions'
        run: pip list | grep -E "^scenario|^gym-ignition"

      - name: '[🐍|scenario] Python Tests'
        shell: bash -i -e {0}
        run: pytest -m "scenario"

      - name: '[🚨|scenario] Python Tests with Valgrind'
        shell: bash -i -e {0}
        if: failure()
        run: |
          sudo apt-get install -y --no-install-recommends valgrind
          pip install colour-valgrind
          valgrind --log-file=/tmp/valgrind.log pytest -m "scenario" || colour-valgrind -t /tmp/valgrind.log

      - name: '[🐍|gym-ignition] Python Tests'
        shell: bash -i -e {0}
        run: pytest -m "gym_ignition"

      - name: '[🚨|gym-ignition] Python Tests with Valgrind'
        shell: bash -i -e {0}
        if: failure()
        run: |
          sudo apt-get install -y --no-install-recommends valgrind
          pip install colour-valgrind
          valgrind --log-file=/tmp/valgrind.log pytest -m "gym_ignition" || colour-valgrind -t /tmp/valgrind.log

      # ============================
      # Upload artifacts (only User)
      # ============================

      - name: '🗑️ Remove external wheels'
        if: matrix.type == 'User'
        run: find dist/ -type f -not -name 'scenario-*' -delete -print

      # We have to trick PyPI that our wheels are manylinux2014 even if they are not.
      # Unfortunately we cannot create self-contained wheels (neither the PEP600 perennial)
      # due to the Ignition architecture.
      - name: '📝 Rename scenario wheel'
        if: matrix.type == 'User' && contains(matrix.os, 'ubuntu')
        run: |
          ls dist/
          find dist/ -type f -name "*.whl" -exec rename.ul linux manylinux2014 {} +
          ls dist/

      - name: '🔍 Inspect dist folder'
        if: matrix.type == 'User'
        run: ls -lah dist/

      - name: '⬆️ Upload artifacts'
        uses: actions/upload-artifact@v2
        if: matrix.type == 'User' && matrix.ignition == 'fortress'
        with:
          path: dist/*
          name: dist

      # =======
      # Website
      # =======

      - name: '⬇️ Install website dependencies'
        run: |
          sudo apt-get update
          sudo apt-get install -y doxygen texlive-font-utils

      - name: '🔍 Inspect metadata'
        run: sphinx-multiversion --dump-metadata docs/sphinx/ build/

      # This is necessary because otherwise the check for uncommitted apidoc
      # only detects additions, not removals.
      - name: '🗑️ Remove apidoc folder'
        run: rm -r docs/sphinx/apidoc

      - name: '🏗️ Build sphinx website'
        shell: bash -i -e {0}
        run: |
          [[ -d build ]] && sudo chown -R $(id -u):$(id -g) build/
          cmake -S . -B build/ -DBUILD_DOCS:BOOL=ON
          cmake --build build/ --target sphinx

      - name: '🔍 Check new uncommitted apidoc'
        run: test $(git status --porcelain | wc -l) -eq 0

      - name: '🔍 git status'
        if: ${{ failure() }}
        run: |
          git status
          git diff

      - name: '⬆️ Upload website folder'
        uses: actions/upload-artifact@v2
        if: matrix.type == 'User' && matrix.ignition == 'fortress' && contains(matrix.os, 'ubuntu')
        with:
          path: build/html
          name: website
          retention-days: 1

# ===================
  website-deployment:
# ===================
    name: 'Website Deployment'
    if: always() && needs.build-and-test.result == 'success'
    needs: [ build-and-test ]
    runs-on: ubuntu-latest
    steps:

      - name: '⬇️ Download website folder'
        uses: actions/download-artifact@v2
        with:
          path: build/html
          name: website

      - name: '🔍 Inspect html folder'
        run: ls -lah build/html

      - name: '🚀 Deploy'
        uses: JamesIves/github-pages-deploy-action@releases/v3
        if: |
          github.event_name == 'push' &&
          github.repository == 'robotology/gym-ignition' &&
          (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/devel')
        with:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          BRANCH: gh-pages
          FOLDER: build/html
          CLEAN: true
          CLEAN_EXCLUDE: '[".gitignore", ".nojekyll"]'

# =================
  python-packaging:
# =================
    name: 'Python packaging'
    if: always() && needs.build-and-test.result == 'success'
    needs: [ build-and-test ]
    runs-on: ubuntu-latest
    steps:

      - name: '🔍️ Inspect Environment'
        run: |
          env | grep ^GITHUB
          echo ""
          cat ${GITHUB_EVENT_PATH}
          echo ""
          env

      # Any Python3 version is ok in this job
      - name: '🐍 Initialize Python'
        uses: actions/setup-python@v2
        with:
          python-version: 3.8

      - name: '🔀 Clone repository'
        uses: actions/checkout@master
      - name: '🔀 Download all refs'
        run: git fetch --prune --unshallow

      # ===============
      # Download wheels
      # ===============

      - name: '⬇️ Download scenario wheels'
        uses: actions/download-artifact@v2
        with:
          path: dist
          name: dist

      - name: '🔍 Inspect dist folder'
        run: ls -lah dist/

      # ===============
      # Create packages
      # ===============

      # We use build to create sdist. Also pipx would work.
      # https://github.com/pypa/build
      # Compared to calling setup.py, the advantage of these tools is that
      # they automatically handle the build dependencies.
      - name: '🐍️️ Install dependencies'
        run: pip install build

      - name: '[📦|scenario]️ Create sdist'
        run: python -m build --sdist scenario/ -o dist/

      - name: '[📦|gym-ignition]️ Create sdist and wheel'
        run: python -m build .

      # ================
      # Upload artifacts
      # ================

      - name: '🗑️ Remove external packages'
        run: find dist/ -type f -not \( -name '*scenario-*' -o -name '*gym_ignition-*' \) -delete -print

      - name: '🔍 Check packages'
        run: pipx run twine check dist/*

      - name: '🔍 Inspect dist folder'
        run: ls -lah dist/

      - name: '⬆️ Upload artifacts'
        uses: actions/upload-artifact@v2
        with:
          path: dist/*
          name: dist

# ============
  upload_pypi:
# ============
    name: Publish to PyPI
    if: always() && needs.build-and-test.result == 'success' && needs.python-packaging.result == 'success'
    needs:
      - build-and-test
      - python-packaging
    runs-on: ubuntu-latest
    # Devel branch produces pre-releases.
    # GitHub releases produce stable releases.

    steps:

      # Needed only to extract from the git repo the last revision
      - name: '🔀 Clone repository'
        uses: actions/checkout@master
      - name: '🔀 Download all refs'
        run: git fetch --prune --unshallow

      - name: '⬇️ Download Python packages'
        uses: actions/download-artifact@v2
        with:
          path: dist
          name: dist

      - name: '🔍 Inspect dist folder'
        run: ls -lah dist/

      # Validate the last tag accordingly to PEP440
      # From https://stackoverflow.com/a/37972030/12150968
      - name: '📌 Check PEP440 compliance'
        if: github.event_name == 'release'
        run: |
          sudo apt-get update
          sudo apt-get install -y source-highlight
          last_tag_with_v="$(git describe --abbrev=0 --tags)"
          last_tag=${last_tag_with_v#v}
          rel_regexp='^(\d+!)?(\d+)(\.\d+)+([\.\-\_])?((a(lpha)?|b(eta)?|c|r(c|ev)?|pre(view)?)\d*)?(\.?(post|dev)\d*)?$'
          echo ""
          echo $last_tag
          echo ""
          check-regexp ${rel_regexp} ${last_tag}
          match=$(check-regexp ${rel_regexp} ${last_tag} | grep matches | cut -d ' ' -f 5)
          test $match -eq 1 && true

      - name: '⬆️ Publish packages to PyPI'
        if: |
          github.repository == 'robotology/gym-ignition' &&
          ((github.event_name == 'release' && github.event.action == 'published') ||
           (github.event_name == 'push' && github.ref == 'refs/heads/devel'))
        uses: pypa/gh-action-pypi-publish@master
        with:
          user: __token__
          password: ${{ secrets.PYPI_TOKEN }}
          skip_existing: true


================================================
FILE: .github/workflows/docker.yml
================================================
name: Docker Images

on:
  push:
    paths:
      - ".docker/*"
      - ".github/workflows/docker.yml"
    branches: ["**"]
    tags-ignore: ["**"]
  pull_request:
    paths:
      - ".docker/*"
      - ".github/workflows/docker.yml"
  workflow_dispatch:
  schedule:
    # Execute a weekly build on Monday at 2AM UTC
    - cron:  '0 2 * * 1'

jobs:
  docker:
    name: 'diegoferigo/gym-ignition:${{ matrix.tag }}'
    runs-on: ubuntu-latest
    strategy:
      max-parallel: 1
      matrix:
        baseimage: ['ubuntu:bionic']
        tag:
          - base
          - ci-master
          - ci-devel
          - pypi-master
          - pypi-devel
          #- latest
          - nightly

    steps:

      # Use the branch that triggered the workflow for push and pull_request events
      - uses: actions/checkout@master
        if: github.event_name != 'schedule'

      # Use devel branch for scheduled builds
      - uses: actions/checkout@master
        with:
          ref: 'refs/heads/devel'
        if: github.event_name == 'schedule'

      - name: Build
        env:
          TAG: ${{ matrix.tag }}
        run: |
          cd .docker
          docker-compose build ${TAG}

      - name: Login
        if: |
          github.repository == 'robotology/gym-ignition' &&
          github.event_name != 'pull_request' &&
          (github.event_name == 'schedule' || github.ref == 'refs/heads/devel')
        env:
          DOCKER_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
          DOCKER_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }}
        run: echo ${DOCKER_PASSWORD} | docker login --username ${DOCKER_USERNAME} --password-stdin

      - name: Push
        if: |
          github.repository == 'robotology/gym-ignition' &&
          github.event_name != 'pull_request' &&
          (github.event_name == 'schedule' || github.ref == 'refs/heads/devel')
        run: docker push diegoferigo/gym-ignition:${{ matrix.tag }}


================================================
FILE: .github/workflows/style.yml
================================================
name: Code Style

on:
  push:
    branches: ["**"]
    tags-ignore: ["**"]
  pull_request:
  workflow_dispatch:

jobs:

  clang-format:

    name: clang-format
    runs-on: ubuntu-latest

    steps:

      - name: "🔀 Checkout repository"
        uses: actions/checkout@v2

      - name: "⬇️️ Install dependencies"
        run: sudo apt-get install -y --no-install-recommends colordiff

      - name: "📝 Format C++"
        uses: diegoferigo/gh-action-clang-format@main
        id: format
        with:
          style: file
          pattern: |
            *.h
            *.cpp

      - name: "🔍️ Inspect style diff"
        if: failure()
        run: printf "${{ steps.format.outputs.diff }}" | colordiff

  black:

    name: black
    runs-on: ubuntu-latest

    steps:

      - name: "🔀 Checkout repository"
        uses: actions/checkout@v2

      - name: '🐍 Initialize Python'
        uses: actions/setup-python@v2
        with:
          python-version: "3.8"

      - name: "📝 Black Code Formatter"
        uses: psf/black@stable
        with:
          options: --check --diff --color

  isort:

    name: isort
    runs-on: ubuntu-latest

    steps:

      - name: "🔀 Checkout repository"
        uses: actions/checkout@v2

      - name: '🐍 Initialize Python'
        uses: actions/setup-python@v2
        with:
          python-version: "3.8"

      - name: "📝 isort"
        uses: isort/isort-action@master
        with:
          configuration: --check --diff --color


================================================
FILE: .gitignore
================================================
*.mexa64
*.mexmaci64
*.autosave
*.original
*~
.DS_Store
build*
*.bak
*.old
CMakeLists.txt.*
Copy_of_*
__pycache__
*.egg-info
*.cache
.idea*
**/dist/*
.egg*


================================================
FILE: CMakeLists.txt
================================================
# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

# This file is here only to allow build systems to find the
# real CMake project that is stored in the scenario/ folder.
cmake_minimum_required(VERSION 3.16)
project(scenario)
add_subdirectory(scenario)

# The uninstall target resource must be included in the top-level CMakeLists
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/scenario/cmake)
include(AddUninstallTarget)

# =============
# DOCUMENTATION
# =============

if(BUILD_DOCS)
    add_subdirectory(docs)
endif()


================================================
FILE: LICENSE
================================================
                   GNU LESSER GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.


  This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.

  0. Additional Definitions.

  As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.

  "The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.

  An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.

  A "Combined Work" is a work produced by combining or linking an
Application with the Library.  The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".

  The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.

  The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.

  1. Exception to Section 3 of the GNU GPL.

  You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.

  2. Conveying Modified Versions.

  If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:

   a) under this License, provided that you make a good faith effort to
   ensure that, in the event an Application does not supply the
   function or data, the facility still operates, and performs
   whatever part of its purpose remains meaningful, or

   b) under the GNU GPL, with none of the additional permissions of
   this License applicable to that copy.

  3. Object Code Incorporating Material from Library Header Files.

  The object code form of an Application may incorporate material from
a header file that is part of the Library.  You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:

   a) Give prominent notice with each copy of the object code that the
   Library is used in it and that the Library and its use are
   covered by this License.

   b) Accompany the object code with a copy of the GNU GPL and this license
   document.

  4. Combined Works.

  You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:

   a) Give prominent notice with each copy of the Combined Work that
   the Library is used in it and that the Library and its use are
   covered by this License.

   b) Accompany the Combined Work with a copy of the GNU GPL and this license
   document.

   c) For a Combined Work that displays copyright notices during
   execution, include the copyright notice for the Library among
   these notices, as well as a reference directing the user to the
   copies of the GNU GPL and this license document.

   d) Do one of the following:

       0) Convey the Minimal Corresponding Source under the terms of this
       License, and the Corresponding Application Code in a form
       suitable for, and under terms that permit, the user to
       recombine or relink the Application with a modified version of
       the Linked Version to produce a modified Combined Work, in the
       manner specified by section 6 of the GNU GPL for conveying
       Corresponding Source.

       1) Use a suitable shared library mechanism for linking with the
       Library.  A suitable mechanism is one that (a) uses at run time
       a copy of the Library already present on the user's computer
       system, and (b) will operate properly with a modified version
       of the Library that is interface-compatible with the Linked
       Version.

   e) Provide Installation Information, but only if you would otherwise
   be required to provide such information under section 6 of the
   GNU GPL, and only to the extent that such information is
   necessary to install and execute a modified version of the
   Combined Work produced by recombining or relinking the
   Application with a modified version of the Linked Version. (If
   you use option 4d0, the Installation Information must accompany
   the Minimal Corresponding Source and Corresponding Application
   Code. If you use option 4d1, you must provide the Installation
   Information in the manner specified by section 6 of the GNU GPL
   for conveying Corresponding Source.)

  5. Combined Libraries.

  You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:

   a) Accompany the combined library with a copy of the same work based
   on the Library, uncombined with any other library facilities,
   conveyed under the terms of this License.

   b) Give prominent notice with the combined library that part of it
   is a work based on the Library, and explaining where to find the
   accompanying uncombined form of the same work.

  6. Revised Versions of the GNU Lesser General Public License.

  The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.

  Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.

  If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.


================================================
FILE: README.md
================================================
<p align="center">
<h1 align="center">gym-ignition</h1>
</p>

<div align="center">
<table>
    <tbody>
         <tr>
            <td align="center">
                <a href="https://github.com/robotology/gym-ignition/actions">
                <img src="https://github.com/robotology/gym-ignition/workflows/CI/CD/badge.svg" alt="CICD" />
                </a>
                <a href="https://github.com/robotology/gym-ignition/actions">
                <img src="https://github.com/robotology/gym-ignition/workflows/Docker%20Images/badge.svg" alt="Docker Images" />
                </a>
                <a href="https://www.codacy.com/gh/robotology/gym-ignition/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=robotology/gym-ignition&amp;utm_campaign=Badge_Grade">
                <img src="https://api.codacy.com/project/badge/Grade/5536b05f8be94483b64ee883e7170a39" alt="Codacy Badge" />
                </a>
            </td>
        </tr>   
        <tr>
            <td align="center">
                <a href="https://pypi.org/project/gym-ignition/">
                <img src="https://img.shields.io/pypi/v/gym-ignition.svg" />
                </a>
                <a href="https://pypi.org/project/gym-ignition/">
                <img src="https://img.shields.io/pypi/pyversions/gym-ignition.svg" />
                </a>
                <a href="https://pypi.org/project/gym-ignition/">
                <img src="https://img.shields.io/pypi/status/gym-ignition.svg" />
                </a>
                <a href="https://pypi.org/project/gym-ignition/">
                <img src="https://img.shields.io/pypi/format/gym-ignition.svg" />
                </a>
                <a href="https://pypi.org/project/gym-ignition/">
                <img src="https://img.shields.io/pypi/l/gym-ignition.svg" />
                </a>
            </td>
        </tr>
    </tbody>
</table>
</div>

> ⚠️ **Warning** ⚠️
>
> This project is no longer actively maintained, and development has stalled.
> For an in-depth description of the current status and actionable steps to revive development, please consult [robotology/gym-ignition#430]([url](https://github.com/robotology/gym-ignition/issues/430)).

||||
|:---:|:---:|:---:|
| ![][pendulum] | ![][panda] | ![][icub] |

[icub]: https://user-images.githubusercontent.com/469199/99262746-9e021a80-281e-11eb-9df1-d70134b0801a.png
[panda]: https://user-images.githubusercontent.com/469199/99263111-0cdf7380-281f-11eb-9cfe-338b2aae0503.png
[pendulum]: https://user-images.githubusercontent.com/469199/99262383-321fb200-281e-11eb-89cc-cc31f590daa3.png

## Description

**gym-ignition** is a framework to create **reproducible robotics environments** for reinforcement learning research.

It is based on the [ScenarIO](scenario/) project which provides the low-level APIs to interface with the Ignition Gazebo simulator.
By default, RL environments share a lot of boilerplate code, e.g. for initializing the simulator or structuring the classes
to expose the `gym.Env` interface.
Gym-ignition provides the [`Task`](python/gym_ignition/base/task.py) and [`Runtime`](python/gym_ignition/base/runtime.py)
abstractions that help you focusing on the development of the decision-making logic rather than engineering.
It includes [randomizers](python/gym_ignition/randomizers) to simplify the implementation of domain randomization
of models, physics, and tasks.
Gym-ignition also provides powerful dynamics algorithms compatible with both fixed-base and floating-based robots by
exploiting [robotology/idyntree](https://github.com/robotology/idyntree/) and exposing
[high-level functionalities](python/gym_ignition/rbd/idyntree).

Gym-ignition does not provide out-of-the-box environments ready to be used.
Rather, its aim is simplifying and streamlining their development.
Nonetheless, for illustrative purpose, it includes canonical examples in the
[`gym_ignition_environments`](python/gym_ignition_environments) package.

Visit the [website][website] for more information about the project.

[website]: https://robotology.github.io/gym-ignition

## Installation

1. First, follow the installation instructions of [ScenarIO](scenario/).
2. `pip install gym-ignition`, preferably in a [virtual environment](https://docs.python.org/3.8/tutorial/venv.html).

## Contributing

You can visit our community forum hosted in [GitHub Discussions](https://github.com/robotology/gym-ignition/discussions).
Even without coding skills, replying user's questions is a great way of contributing.
If you use gym-ignition in your application and want to show it off, visit the
[Show and tell](https://github.com/robotology/gym-ignition/discussions/categories/show-and-tell) section!
You can advertise there your environments created with gym-ignition.

Pull requests are welcome.

For major changes, please open a [discussion](https://github.com/robotology/gym-ignition/discussions)
first to propose what you would like to change.

## Citation

```bibtex
@INPROCEEDINGS{ferigo2020gymignition,
    title={Gym-Ignition: Reproducible Robotic Simulations for Reinforcement Learning},
    author={D. {Ferigo} and S. {Traversaro} and G. {Metta} and D. {Pucci}},
    booktitle={2020 IEEE/SICE International Symposium on System Integration (SII)},
    year={2020},
    pages={885-890},
    doi={10.1109/SII46433.2020.9025951}
} 
```

## License

[LGPL v2.1](https://choosealicense.com/licenses/lgpl-2.1/) or any later version.

---

**Disclaimer:** Gym-ignition is an independent project and is not related by any means to OpenAI and Open Robotics.


================================================
FILE: docs/CMakeLists.txt
================================================
# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

# This variable is filled from the doxygen/ folder.
# Defined here empty to remember that it exists in this scope.
set(DOXYGEN_OUTPUT_DIRECTORY "")

add_subdirectory(doxygen)
add_subdirectory(sphinx)


================================================
FILE: docs/doxygen/CMakeLists.txt
================================================
# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

find_package(Doxygen REQUIRED)

set(DOXYGEN_GENERATE_XML YES)
set(DOXYGEN_GENERATE_HTML NO)
set(DOXYGEN_GENERATE_LATEX YES)
set(DOXYGEN_FILE_PATTERNS "*.h")
set(DOXYGEN_BUILTIN_STL_SUPPORT YES)
set(DOXYGEN_EXCLUDE_PATTERNS
    */components/* */plugins/* */details/* */private/*
    */examples/* */tests/* */gympp/*)

doxygen_add_docs(
    doxygen
    ${PROJECT_SOURCE_DIR}
    COMMENT "Generate man pages"
)

# This is required by Sphinx to find Doxygen XMLs
set(DOXYGEN_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE)


================================================
FILE: docs/sphinx/CMakeLists.txt
================================================
# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

# Useful folders:
#
# 1. The folder containing the Python packages
# 2. The folder containing the bindings Python modules
#
set(PYTHON_PACKAGES_DIR "${CMAKE_SOURCE_DIR}/python")
set(BINDINGS_MODULES_DIR "${PROJECT_BINARY_DIR}/scenario/bindings")

# =============
# APIDOC TARGET
# =============

# This target generates the apidoc files of the Python modules and stores
# them in the docs/sphinx/ source folder.
# In order to make the multiversion website work, they need to be committed
# when they change.
#
# The files in the following folders are replaced:
#
# - docs/sphinx/scenario
# - docs/sphinx/gym_ignition
# - docs/sphinx/gym_ignition_environments

if (NOT TARGET ScenarioSwig::Core)
    message(FATAL_ERROR "Target ScenarioSwig::Core not found")
endif()

if (NOT TARGET ScenarioSwig::Gazebo)
    message(FATAL_ERROR "Target ScenarioSwig::Gazebo not found")
endif()

find_package(SphinxApidoc REQUIRED)
add_custom_target(apidoc ALL DEPENDS
    doxygen ScenarioSwig::Core ScenarioSwig::Gazebo)

add_custom_command(
    TARGET apidoc POST_BUILD
    COMMAND
    ${SPHINX_APIDOC_EXECUTABLE} --force
    --no-toc --module-first --maxdepth 4
    -t ${CMAKE_CURRENT_SOURCE_DIR}/_templates
    -o ${CMAKE_CURRENT_SOURCE_DIR}/apidoc/gym-ignition
    ${PYTHON_PACKAGES_DIR}/gym_ignition
    COMMENT "Building <gym-ignition> apidoc")

add_custom_command(
    TARGET apidoc POST_BUILD
    COMMAND
    ${SPHINX_APIDOC_EXECUTABLE} --force
    --no-toc --module-first --maxdepth 4
    -t ${CMAKE_CURRENT_SOURCE_DIR}/_templates
    -o ${CMAKE_CURRENT_SOURCE_DIR}/apidoc/gym-ignition-environments
    ${PYTHON_PACKAGES_DIR}/gym_ignition_environments
    COMMENT "Building <gym-ignition-environments> apidoc")

add_custom_command(
    TARGET apidoc POST_BUILD
    COMMAND
    ${SPHINX_APIDOC_EXECUTABLE} --force
    --no-toc --module-first --maxdepth 4
    -t ${CMAKE_CURRENT_SOURCE_DIR}/_templates
    -o ${CMAKE_CURRENT_SOURCE_DIR}/apidoc/scenario
    ${BINDINGS_MODULES_DIR}
    COMMENT "Building <scenario> apidoc")

# =============
# SPHINX TARGET
# =============

find_package(Sphinx REQUIRED)
find_package(SphinxMultiVersion REQUIRED)

if(${DOXYGEN_OUTPUT_DIRECTORY} STREQUAL "")
    message(FATAL_ERROR "Doxygen was not configured properly")
endif()

set(SPHINX_BUILD ${CMAKE_BINARY_DIR}/html)
set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR})

# Extend the Python path including before generating the website
set(SPHINX_CMD export PYTHONPATH="${PYTHON_PACKAGES_DIR}:${BINDINGS_MODULES_DIR}:$ENV{PYTHONPATH}" &&)

# Sphinx build command
list(APPEND SPHINX_CMD
    ${SPHINX_MULTIVERSION_EXECUTABLE}
    ${SPHINX_SOURCE} ${SPHINX_BUILD}
    -D breathe_projects.scenario="${DOXYGEN_OUTPUT_DIRECTORY}/xml")

# Generate the website
add_custom_target(sphinx ALL
    DEPENDS apidoc
    COMMAND ${SPHINX_CMD}
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    COMMENT "Generating documentation with Sphinx")

# Disable GitHub pages autogeneration
add_custom_command(
    TARGET sphinx POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E touch "${SPHINX_BUILD}/.nojekyll"
    COMMENT "Disabling Jekyll in html folder")

# Handle redirect
add_custom_command(
    TARGET sphinx POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/index.html" "${SPHINX_BUILD}"
    COMMENT "Copying html redirect to html folder")


================================================
FILE: docs/sphinx/_templates/module.rst_t
================================================
{%- if show_headings %}
{{- [basename, "module"] | join(' ') | e | heading }}

{% endif -%}
.. automodule:: {{ qualname }}
{%- for option in automodule_options %}
   :{{ option }}:
{%- endfor %}


================================================
FILE: docs/sphinx/_templates/package.rst_t
================================================
{%- macro automodule(modname, options) -%}
.. automodule:: {{ modname }}
{%- for option in options %}
   :{{ option }}:
{%- endfor %}
{%- endmacro %}

{%- macro toctree(docnames) -%}
.. toctree::
   :maxdepth: {{ maxdepth }}
{% for docname in docnames %}
   {{ docname }}
{%- endfor %}
{%- endmacro %}

{%- if is_namespace %}
{{- [pkgname, "namespace"] | join(" ") | e | heading }}
{% else %}
{{- pkgname | e | heading }}
{% endif %}

{%- if modulefirst and not is_namespace %}
{{ automodule(pkgname, automodule_options) }}
{% endif %}

{%- if subpackages %}

{{ toctree(subpackages) }}
{% endif %}

{%- if submodules %}
{% if separatemodules %}
{{ toctree(submodules) }}
{% else %}
{%- for submodule in submodules %}
{% if show_headings %}
{{- submodule | e | heading(2) }}
{% endif %}
{{ automodule(submodule, automodule_options) }}
{% endfor %}
{%- endif %}
{%- endif %}

{%- if not modulefirst and not is_namespace %}
Module contents
---------------

{{ automodule(pkgname, automodule_options) }}
{% endif %}


================================================
FILE: docs/sphinx/_templates/toc.rst_t
================================================
{{ header | heading }}

.. toctree::
   :maxdepth: {{ maxdepth }}
{% for docname in docnames %}
   {{ docname }}
{%- endfor %}


================================================
FILE: docs/sphinx/_templates/versioning.html
================================================
{% if versions %}
<nav id="bd-docs-nav" class="bd-links" aria-label="Versions navigation">
  <div class="bd-toc-item active">
    <p class="caption">
      <span class="caption-text">{{ _('Doc Versions') }}</span>
    </p>
    <ul class="nav bd-sidenav">
      {%- for item in versions %}
      <li class="toctree-l1"><a class="reference internal" href="{{ item.url }}">{{ item.name }}</a></li>
      {%- endfor %}
    </ul>
  </div>
</nav>
{% endif %}


================================================
FILE: docs/sphinx/_templates/versions.html
================================================
{%- if current_version %}
<div class="rst-versions" data-toggle="rst-versions" role="note" aria-label="versions">
  <span class="rst-current-version" data-toggle="rst-current-version">
    <span class="fa fa-book"> Other Versions</span>
    v: {{ current_version.name }}
    <span class="fa fa-caret-down"></span>
  </span>
  <div class="rst-other-versions">
    {%- if versions.tags %}
    <dl>
      <dt>Tags</dt>
      {%- for item in versions.tags %}
      <dd><a href="{{ item.url }}">{{ item.name }}</a></dd>
      {%- endfor %}
    </dl>
    {%- endif %}
    {%- if versions.branches %}
    <dl>
      <dt>Branches</dt>
      {%- for item in versions.branches %}
      <dd><a href="{{ item.url }}">{{ item.name }}</a></dd>
      {%- endfor %}
    </dl>
    {%- endif %}
  </div>
</div>
{%- endif %}

================================================
FILE: docs/sphinx/apidoc/gym-ignition/gym_ignition.base.rst
================================================
gym\_ignition.base
==================

.. automodule:: gym_ignition.base
   :members:
   :undoc-members:
   :show-inheritance:


gym\_ignition.base.runtime
--------------------------

.. automodule:: gym_ignition.base.runtime
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition.base.task
-----------------------

.. automodule:: gym_ignition.base.task
   :members:
   :undoc-members:
   :show-inheritance:


================================================
FILE: docs/sphinx/apidoc/gym-ignition/gym_ignition.context.gazebo.rst
================================================
gym\_ignition.context.gazebo
============================

.. automodule:: gym_ignition.context.gazebo
   :members:
   :undoc-members:
   :show-inheritance:


gym\_ignition.context.gazebo.controllers
----------------------------------------

.. automodule:: gym_ignition.context.gazebo.controllers
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition.context.gazebo.plugin
-----------------------------------

.. automodule:: gym_ignition.context.gazebo.plugin
   :members:
   :undoc-members:
   :show-inheritance:


================================================
FILE: docs/sphinx/apidoc/gym-ignition/gym_ignition.context.rst
================================================
gym\_ignition.context
=====================

.. automodule:: gym_ignition.context
   :members:
   :undoc-members:
   :show-inheritance:


.. toctree::
   :maxdepth: 4

   gym_ignition.context.gazebo


================================================
FILE: docs/sphinx/apidoc/gym-ignition/gym_ignition.randomizers.model.rst
================================================
gym\_ignition.randomizers.model
===============================

.. automodule:: gym_ignition.randomizers.model
   :members:
   :undoc-members:
   :show-inheritance:


gym\_ignition.randomizers.model.sdf
-----------------------------------

.. automodule:: gym_ignition.randomizers.model.sdf
   :members:
   :undoc-members:
   :show-inheritance:


================================================
FILE: docs/sphinx/apidoc/gym-ignition/gym_ignition.randomizers.physics.rst
================================================
gym\_ignition.randomizers.physics
=================================

.. automodule:: gym_ignition.randomizers.physics
   :members:
   :undoc-members:
   :show-inheritance:


gym\_ignition.randomizers.physics.dart
--------------------------------------

.. automodule:: gym_ignition.randomizers.physics.dart
   :members:
   :undoc-members:
   :show-inheritance:


================================================
FILE: docs/sphinx/apidoc/gym-ignition/gym_ignition.randomizers.rst
================================================
gym\_ignition.randomizers
=========================

.. automodule:: gym_ignition.randomizers
   :members:
   :undoc-members:
   :show-inheritance:


.. toctree::
   :maxdepth: 4

   gym_ignition.randomizers.model
   gym_ignition.randomizers.physics


gym\_ignition.randomizers.abc
-----------------------------

.. automodule:: gym_ignition.randomizers.abc
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition.randomizers.gazebo\_env\_randomizer
-------------------------------------------------

.. automodule:: gym_ignition.randomizers.gazebo_env_randomizer
   :members:
   :undoc-members:
   :show-inheritance:


================================================
FILE: docs/sphinx/apidoc/gym-ignition/gym_ignition.rbd.idyntree.rst
================================================
gym\_ignition.rbd.idyntree
==========================

.. automodule:: gym_ignition.rbd.idyntree
   :members:
   :undoc-members:
   :show-inheritance:


gym\_ignition.rbd.idyntree.helpers
----------------------------------

.. automodule:: gym_ignition.rbd.idyntree.helpers
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition.rbd.idyntree.inverse\_kinematics\_nlp
---------------------------------------------------

.. automodule:: gym_ignition.rbd.idyntree.inverse_kinematics_nlp
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition.rbd.idyntree.kindyncomputations
---------------------------------------------

.. automodule:: gym_ignition.rbd.idyntree.kindyncomputations
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition.rbd.idyntree.numpy
--------------------------------

.. automodule:: gym_ignition.rbd.idyntree.numpy
   :members:
   :undoc-members:
   :show-inheritance:


================================================
FILE: docs/sphinx/apidoc/gym-ignition/gym_ignition.rbd.rst
================================================
gym\_ignition.rbd
=================

.. automodule:: gym_ignition.rbd
   :members:
   :undoc-members:
   :show-inheritance:


.. toctree::
   :maxdepth: 4

   gym_ignition.rbd.idyntree


gym\_ignition.rbd.conversions
-----------------------------

.. automodule:: gym_ignition.rbd.conversions
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition.rbd.utils
-----------------------

.. automodule:: gym_ignition.rbd.utils
   :members:
   :undoc-members:
   :show-inheritance:


================================================
FILE: docs/sphinx/apidoc/gym-ignition/gym_ignition.rst
================================================
gym\_ignition
=============

.. automodule:: gym_ignition
   :members:
   :undoc-members:
   :show-inheritance:


.. toctree::
   :maxdepth: 4

   gym_ignition.base
   gym_ignition.context
   gym_ignition.randomizers
   gym_ignition.rbd
   gym_ignition.runtimes
   gym_ignition.scenario
   gym_ignition.utils


================================================
FILE: docs/sphinx/apidoc/gym-ignition/gym_ignition.runtimes.rst
================================================
gym\_ignition.runtimes
======================

.. automodule:: gym_ignition.runtimes
   :members:
   :undoc-members:
   :show-inheritance:


gym\_ignition.runtimes.gazebo\_runtime
--------------------------------------

.. automodule:: gym_ignition.runtimes.gazebo_runtime
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition.runtimes.realtime\_runtime
----------------------------------------

.. automodule:: gym_ignition.runtimes.realtime_runtime
   :members:
   :undoc-members:
   :show-inheritance:


================================================
FILE: docs/sphinx/apidoc/gym-ignition/gym_ignition.scenario.rst
================================================
gym\_ignition.scenario
======================

.. automodule:: gym_ignition.scenario
   :members:
   :undoc-members:
   :show-inheritance:


gym\_ignition.scenario.model\_with\_file
----------------------------------------

.. automodule:: gym_ignition.scenario.model_with_file
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition.scenario.model\_wrapper
-------------------------------------

.. automodule:: gym_ignition.scenario.model_wrapper
   :members:
   :undoc-members:
   :show-inheritance:


================================================
FILE: docs/sphinx/apidoc/gym-ignition/gym_ignition.utils.rst
================================================
gym\_ignition.utils
===================

.. automodule:: gym_ignition.utils
   :members:
   :undoc-members:
   :show-inheritance:


gym\_ignition.utils.logger
--------------------------

.. automodule:: gym_ignition.utils.logger
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition.utils.math
------------------------

.. automodule:: gym_ignition.utils.math
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition.utils.misc
------------------------

.. automodule:: gym_ignition.utils.misc
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition.utils.resource\_finder
------------------------------------

.. automodule:: gym_ignition.utils.resource_finder
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition.utils.scenario
----------------------------

.. automodule:: gym_ignition.utils.scenario
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition.utils.typing
--------------------------

.. automodule:: gym_ignition.utils.typing
   :members:
   :undoc-members:
   :show-inheritance:


================================================
FILE: docs/sphinx/apidoc/gym-ignition-environments/gym_ignition_environments.models.rst
================================================
gym\_ignition\_environments.models
==================================

.. automodule:: gym_ignition_environments.models
   :members:
   :undoc-members:
   :show-inheritance:


gym\_ignition\_environments.models.cartpole
-------------------------------------------

.. automodule:: gym_ignition_environments.models.cartpole
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition\_environments.models.icub
---------------------------------------

.. automodule:: gym_ignition_environments.models.icub
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition\_environments.models.panda
----------------------------------------

.. automodule:: gym_ignition_environments.models.panda
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition\_environments.models.pendulum
-------------------------------------------

.. automodule:: gym_ignition_environments.models.pendulum
   :members:
   :undoc-members:
   :show-inheritance:


================================================
FILE: docs/sphinx/apidoc/gym-ignition-environments/gym_ignition_environments.randomizers.rst
================================================
gym\_ignition\_environments.randomizers
=======================================

.. automodule:: gym_ignition_environments.randomizers
   :members:
   :undoc-members:
   :show-inheritance:


gym\_ignition\_environments.randomizers.cartpole
------------------------------------------------

.. automodule:: gym_ignition_environments.randomizers.cartpole
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition\_environments.randomizers.cartpole\_no\_rand
----------------------------------------------------------

.. automodule:: gym_ignition_environments.randomizers.cartpole_no_rand
   :members:
   :undoc-members:
   :show-inheritance:


================================================
FILE: docs/sphinx/apidoc/gym-ignition-environments/gym_ignition_environments.rst
================================================
gym\_ignition\_environments
===========================

.. automodule:: gym_ignition_environments
   :members:
   :undoc-members:
   :show-inheritance:


.. toctree::
   :maxdepth: 4

   gym_ignition_environments.models
   gym_ignition_environments.randomizers
   gym_ignition_environments.tasks


================================================
FILE: docs/sphinx/apidoc/gym-ignition-environments/gym_ignition_environments.tasks.rst
================================================
gym\_ignition\_environments.tasks
=================================

.. automodule:: gym_ignition_environments.tasks
   :members:
   :undoc-members:
   :show-inheritance:


gym\_ignition\_environments.tasks.cartpole\_continuous\_balancing
-----------------------------------------------------------------

.. automodule:: gym_ignition_environments.tasks.cartpole_continuous_balancing
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition\_environments.tasks.cartpole\_continuous\_swingup
---------------------------------------------------------------

.. automodule:: gym_ignition_environments.tasks.cartpole_continuous_swingup
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition\_environments.tasks.cartpole\_discrete\_balancing
---------------------------------------------------------------

.. automodule:: gym_ignition_environments.tasks.cartpole_discrete_balancing
   :members:
   :undoc-members:
   :show-inheritance:

gym\_ignition\_environments.tasks.pendulum\_swingup
---------------------------------------------------

.. automodule:: gym_ignition_environments.tasks.pendulum_swingup
   :members:
   :undoc-members:
   :show-inheritance:


================================================
FILE: docs/sphinx/apidoc/scenario/scenario.bindings.rst
================================================
scenario.bindings
=================

.. automodule:: scenario.bindings
   :members:
   :undoc-members:
   :show-inheritance:


scenario.bindings.core
----------------------

.. automodule:: scenario.bindings.core
   :members:
   :undoc-members:
   :show-inheritance:

scenario.bindings.gazebo
------------------------

.. automodule:: scenario.bindings.gazebo
   :members:
   :undoc-members:
   :show-inheritance:


================================================
FILE: docs/sphinx/apidoc/scenario/scenario.rst
================================================
scenario
========

.. automodule:: scenario
   :members:
   :undoc-members:
   :show-inheritance:


.. toctree::
   :maxdepth: 4

   scenario.bindings


================================================
FILE: docs/sphinx/breathe/core.rst
================================================
.. _scenario_core:

Core
====

.. doxygennamespace:: scenario::core
   :project: scenario
   :members:


================================================
FILE: docs/sphinx/breathe/gazebo.rst
================================================
.. _scenario_gazebo:

Gazebo
======

.. doxygennamespace:: scenario::gazebo
   :project: scenario
   :members:


================================================
FILE: docs/sphinx/conf.py
================================================
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Path setup --------------------------------------------------------------

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))

# -- Project information -----------------------------------------------------
from datetime import datetime

project = "gym-ignition"
copyright = f"{datetime.now().year}, Istituto Italiano di Tecnologia"
author = "Diego Ferigo"

# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
    "sphinx.ext.autodoc",
    "sphinx.ext.todo",
    "sphinx.ext.mathjax",
    "sphinx.ext.githubpages",
    "sphinx.ext.napoleon",
    "sphinx.ext.extlinks",
    "sphinx_autodoc_typehints",
    "sphinx_multiversion",
    "sphinx_fontawesome",
    "breathe",
    "sphinx_tabs.tabs",
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = "en"

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]


# -- Options for HTML output -------------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
#
html_theme = "sphinx_book_theme"

# Theme options are theme-specific and customize the look and feel of a theme
# further.  For a list of options available for each theme, see the
# documentation.
html_theme_options = {
    "repository_url": "https://github.com/robotology/gym-ignition",
    "use_repository_button": True,
    "use_issues_button": True,
    "use_edit_page_button": True,
    "path_to_docs": "docs/sphinx",
    "home_page_in_toc": True,
    "use_download_button": False,
    "use_fullscreen_button": True,
    "single_page": False,
}

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
# html_static_path = ['_static']

# The name of the Pygments (syntax highlighting) style to use.
pygments_style = "pastie"


# -- Extension configuration -------------------------------------------------

# -- Options for todo extension ----------------------------------------------

# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True

# -- Options for breathe extension ----------------------------------------------

breathe_default_project = "scenario"

# -- Options for sphinx_multiversion extension ----------------------------------

# From: https://holzhaus.github.io/sphinx-multiversion
smv_prefer_remote_refs = False
smv_remote_whitelist = r"^(origin|upstream)$"
smv_tag_whitelist = r"^dummy"
smv_branch_whitelist = r"^(master|devel|docs/.*)$"
smv_released_pattern = r"^tags/.*$"
smv_outputdir_format = "{ref.name}"

html_sidebars = {
    "**": [
        "sbt-sidebar-nav.html",
        "versioning.html",
        "search-field.html",
        "sbt-sidebar-footer.html",
    ]
}

# -- Options for extlinks extension ----------------------------------
extlinks = {
    "issue": ("https://github.com/robotology/gym-ignition/issues/%s", "#"),
    "pr": ("https://github.com/robotology/gym-ignition/pull/%s", "#"),
}


================================================
FILE: docs/sphinx/getting_started/gym-ignition.rst
================================================
.. _getting_started_gym_ignition:

gym-ignition
************

The previous sections reported the usage of ScenarIO to perform rigid-body simulations of any kind.
The :py:mod:`gym_ignition` Python package provides boilerplate code that use ScenarIO to create environments
for reinforcement learning research compatible with OpenAI Gym.

Beyond the abstractions provided by ScenarIO, gym-ignition introduces the following:

- :py:class:`~gym_ignition.base.runtime.Runtime`: Base class to abstract the runtime of an environment.
  It provides the code that steps the simulator for simulated environments or deals with real-time execution for
  environments running on real robots.
  The implementation for Ignition Gazebo is :py:class:`~gym_ignition.runtimes.gazebo_runtime.GazeboRuntime`.

- :py:class:`~gym_ignition.base.task.Task`: Base class providing the structure of the decision-making logic.
  The code of the task must be independent from the runtime, and only the ScenarIO APIs should be used.
  The active runtime will then execute the task on either simulated or real worlds.

- :py:mod:`gym_ignition.randomizers`: Utilities to develop ``gym.Wrapper`` classes that randomize the environment
  every rollout.
  The implementation for Ignition Gazebo is :py:class:`~gym_ignition.randomizers.gazebo_env_randomizer.GazeboEnvRandomizer`.

- :py:mod:`gym_ignition.rbd`: Utilities commonly used in robotic environments, like inverse kinematics and rigid-body
  dynamics algorithms.
  Refer to :py:class:`~gym_ignition.rbd.idyntree.inverse_kinematics_nlp.InverseKinematicsNLP` and
  :py:class:`~gym_ignition.rbd.idyntree.kindyncomputations.KinDynComputations` for more details.

.. tip::

    If you want to learn more about ``iDynTree``, the two classes we mainly use are ``iDynTree::KinDynComputations`` (`docs <https://robotology.github.io/idyntree/master/classiDynTree_1_1KinDynComputations.html>`__) and ``iDynTree::InverseKinematics`` (`docs <https://robotology.github.io/idyntree/master/classiDynTree_1_1InverseKinematics.html>`__).

    The theory and notation is summarized in `Multibody dynamics notation <https://pure.tue.nl/ws/portalfiles/portal/139293126/A_Multibody_Dynamics_Notation_Revision_2_.pdf>`_.

You can find demo environments created with ``gym-ignition`` in the
`gym_ignition_environments <https://github.com/robotology/gym-ignition/blob/master/python/gym_ignition_environments>`_ folder.
These examples show how to structure a new standalone Python package containing the environment with your robots.

For example, taking the cartpole balancing problem with discrete actions,
the components you need to implement are the following:

- A model :py:class:`~gym_ignition_environments.models.cartpole.CartPole`
  (`model/cartpole.py <https://github.com/robotology/gym-ignition/blob/master/python/gym_ignition_environments/models/cartpole.py>`_)

- A task :py:class:`~gym_ignition_environments.tasks.cartpole_discrete_balancing.CartPoleDiscreteBalancing`
  (`cartpole_discrete_balancing.py <https://github.com/robotology/gym-ignition/blob/master/python/gym_ignition_environments/tasks/cartpole_discrete_balancing.py>`_)

- A randomizer :py:class:`~gym_ignition_environments.randomizers.cartpole.CartpoleEnvRandomizer`
  (`randomizers/cartpole.py <https://github.com/robotology/gym-ignition/blob/master/python/gym_ignition_environments/randomizers/cartpole.py>`_)

- Environment registration as done in `__init__.py <https://github.com/robotology/gym-ignition/blob/master/python/gym_ignition_environments/__init__.py>`_

With all these resources in place, you can run a random policy of the environment as shown in
`launch_cartpole.py <https://github.com/robotology/gym-ignition/blob/master/examples/python/launch_cartpole.py>`_.


================================================
FILE: docs/sphinx/getting_started/manipulation.rst
================================================
.. _getting_started_manipulation:

Manipulation example
********************

This example provides a wider overview of the functionalities currently implemented in gym-ignition.

The code reported below is taken from the example
`panda_pick_and_place.py <https://github.com/robotology/gym-ignition/blob/master/examples/panda_pick_and_place.py>`_.
It shows the following functionalities:

- Download models from `Ignition Fuel <https://app.ignitionrobotics.org/dashboard>`_.
- Insert and remove models during runtime.
- Exploit the high-level :py:class:`~gym_ignition_environments.models.panda.Panda` helper class to insert the manipulator.
- Enable custom C++ controllers (:cpp:class:`scenario::controllers::ComputedTorqueFixedBase`).
- Detect contacts and read contact wrenches.
- Exploit :py:class:`~gym_ignition.rbd.idyntree.inverse_kinematics_nlp.InverseKinematicsNLP`.

.. figure:: https://user-images.githubusercontent.com/469199/99905096-f29a0f80-2cce-11eb-9f1c-002f6c887bc6.png
   :align: center

.. tip::

   This example can be the starting point to develop manipulation environments for robot learning.
   Visit the :ref:`getting_started_gym_ignition` page for more information about how to wrap this code in the resources provided by ``gym_ignition``.

.. note::

   This is an illustrative example. A compliant joint controller is used to move the manipulator, it does not perform any
   trajectory planning and it does not avoid self collisions, which are not enabled in the simulation by default.
   There are cube positions where the joint configuration changes a lot from the previous, generating an abrupt movement
   of the manipulator. When these situations occur, grasping might fail.

.. code-block:: python

    import enum
    import time
    from functools import partial
    from typing import List

    import gym_ignition
    import gym_ignition_environments
    import numpy as np
    from gym_ignition.context.gazebo import controllers
    from gym_ignition.rbd import conversions
    from gym_ignition.rbd.idyntree import inverse_kinematics_nlp
    from scipy.spatial.transform import Rotation as R

    from scenario import core as scenario_core
    from scenario import gazebo as scenario_gazebo

    # Configure verbosity
    scenario_gazebo.set_verbosity(scenario_gazebo.Verbosity_error)

    # Configure numpy output
    np.set_printoptions(precision=4, suppress=True)


    def add_panda_controller(
        panda: gym_ignition_environments.models.panda.Panda, controller_period: float
    ) -> None:

        # Set the controller period
        assert panda.set_controller_period(period=controller_period)

        # Increase the max effort of the fingers
        panda.get_joint(
            joint_name="panda_finger_joint1"
        ).to_gazebo().set_max_generalized_force(max_force=500.0)
        panda.get_joint(
            joint_name="panda_finger_joint2"
        ).to_gazebo().set_max_generalized_force(max_force=500.0)

        # Insert the ComputedTorqueFixedBase controller
        assert panda.to_gazebo().insert_model_plugin(
            *controllers.ComputedTorqueFixedBase(
                kp=[100.0] * (panda.dofs() - 2) + [10000.0] * 2,
                ki=[0.0] * panda.dofs(),
                kd=[17.5] * (panda.dofs() - 2) + [100.0] * 2,
                urdf=panda.get_model_file(),
                joints=panda.joint_names(),
            ).args()
        )

        # Initialize the controller to the current state
        assert panda.set_joint_position_targets(panda.joint_positions())
        assert panda.set_joint_velocity_targets(panda.joint_velocities())
        assert panda.set_joint_acceleration_targets(panda.joint_accelerations())


    def get_panda_ik(
        panda: gym_ignition_environments.models.panda.Panda, optimized_joints: List[str]
    ) -> inverse_kinematics_nlp.InverseKinematicsNLP:

        # Create IK
        ik = inverse_kinematics_nlp.InverseKinematicsNLP(
            urdf_filename=panda.get_model_file(),
            considered_joints=optimized_joints,
            joint_serialization=panda.joint_names(),
        )

        # Initialize IK
        ik.initialize(
            verbosity=1,
            floating_base=False,
            cost_tolerance=1e-8,
            constraints_tolerance=1e-8,
            base_frame=panda.base_frame(),
        )

        # Set the current configuration
        ik.set_current_robot_configuration(
            base_position=np.array(panda.base_position()),
            base_quaternion=np.array(panda.base_orientation()),
            joint_configuration=np.array(panda.joint_positions()),
        )

        # Add the cartesian target of the end effector
        end_effector = "end_effector_frame"
        ik.add_target(
            frame_name=end_effector,
            target_type=inverse_kinematics_nlp.TargetType.POSE,
            as_constraint=False,
        )

        return ik


    def insert_bucket(world: scenario_gazebo.World) -> scenario_gazebo.Model:

        # Insert objects from Fuel
        uri = lambda org, name: f"https://fuel.ignitionrobotics.org/{org}/models/{name}"

        # Download the cube SDF file
        bucket_sdf = scenario_gazebo.get_model_file_from_fuel(
            uri=uri(
                org="GoogleResearch",
                name="Threshold_Basket_Natural_Finish_Fabric_Liner_Small",
            ),
            use_cache=False,
        )

        # Assign a custom name to the model
        model_name = "bucket"

        # Insert the model
        assert world.insert_model(
            bucket_sdf, scenario_core.Pose([0.68, 0, 1.02], [1.0, 0, 0, 1]), model_name
        )

        # Return the model
        return world.get_model(model_name=model_name)


    def insert_table(world: scenario_gazebo.World) -> scenario_gazebo.Model:

        # Insert objects from Fuel
        uri = lambda org, name: f"https://fuel.ignitionrobotics.org/{org}/models/{name}"

        # Download the cube SDF file
        bucket_sdf = scenario_gazebo.get_model_file_from_fuel(
            uri=uri(org="OpenRobotics", name="Table"), use_cache=False
        )

        # Assign a custom name to the model
        model_name = "table"

        # Insert the model
        assert world.insert_model(bucket_sdf, scenario_core.Pose_identity(), model_name)

        # Return the model
        return world.get_model(model_name=model_name)


    def insert_cube_in_operating_area(
        world: scenario_gazebo.World,
    ) -> scenario_gazebo.Model:

        # Insert objects from Fuel
        uri = lambda org, name: f"https://fuel.ignitionrobotics.org/{org}/models/{name}"

        # Download the cube SDF file
        cube_sdf = scenario_gazebo.get_model_file_from_fuel(
            uri=uri(org="openrobotics", name="wood cube 5cm"), use_cache=False
        )

        # Sample a random position
        random_position = np.random.uniform(low=[0.2, -0.3, 1.01], high=[0.4, 0.3, 1.01])

        # Get a unique name
        model_name = gym_ignition.utils.scenario.get_unique_model_name(
            world=world, model_name="cube"
        )

        # Insert the model
        assert world.insert_model(
            cube_sdf, scenario_core.Pose(random_position, [1.0, 0, 0, 0]), model_name
        )

        # Return the model
        return world.get_model(model_name=model_name)


    def solve_ik(
        target_position: np.ndarray,
        target_orientation: np.ndarray,
        ik: inverse_kinematics_nlp.InverseKinematicsNLP,
    ) -> np.ndarray:

        quat_xyzw = R.from_euler(seq="y", angles=90, degrees=True).as_quat()

        ik.update_transform_target(
            target_name=ik.get_active_target_names()[0],
            position=target_position,
            quaternion=conversions.Quaternion.to_wxyz(xyzw=quat_xyzw),
        )

        # Run the IK
        ik.solve()

        return ik.get_reduced_solution().joint_configuration


    def end_effector_reached(
        position: np.array,
        end_effector_link: scenario_core.Link,
        max_error_pos: float = 0.01,
        max_error_vel: float = 0.5,
        mask: np.ndarray = np.array([1.0, 1.0, 1.0]),
    ) -> bool:

        masked_target = mask * position
        masked_current = mask * np.array(end_effector_link.position())

        return (
            np.linalg.norm(masked_current - masked_target) < max_error_pos
            and np.linalg.norm(end_effector_link.world_linear_velocity()) < max_error_vel
        )


    def get_unload_position(bucket: scenario_core.Model) -> np.ndarray:

        return bucket.base_position() + np.array([0, 0, 0.3])


    class FingersAction(enum.Enum):

        OPEN = enum.auto()
        CLOSE = enum.auto()


    def move_fingers(
        panda: gym_ignition_environments.models.panda.Panda, action: FingersAction
    ) -> None:

        # Get the joints of the fingers
        finger1 = panda.get_joint(joint_name="panda_finger_joint1")
        finger2 = panda.get_joint(joint_name="panda_finger_joint2")

        if action is FingersAction.OPEN:
            finger1.set_position_target(position=finger1.position_limit().max)
            finger2.set_position_target(position=finger2.position_limit().max)

        if action is FingersAction.CLOSE:
            finger1.set_position_target(position=finger1.position_limit().min)
            finger2.set_position_target(position=finger2.position_limit().min)


    # ====================
    # INITIALIZE THE WORLD
    # ====================

    # Get the simulator and the world
    gazebo, world = gym_ignition.utils.scenario.init_gazebo_sim(
        step_size=0.001, real_time_factor=2.0, steps_per_run=1
    )

    # Open the GUI
    gazebo.gui()
    time.sleep(3)
    gazebo.run(paused=True)

    # Insert the Panda manipulator
    panda = gym_ignition_environments.models.panda.Panda(
        world=world, position=[-0.1, 0, 1.0]
    )

    # Disable joint velocity limits
    _ = [j.to_gazebo().set_velocity_limit(1_000) for j in panda.joints()]

    # Enable contacts only for the finger links
    panda.get_link("panda_leftfinger").to_gazebo().enable_contact_detection(True)
    panda.get_link("panda_rightfinger").to_gazebo().enable_contact_detection(True)

    # Process model insertion in the simulation
    gazebo.run(paused=True)

    # Monkey patch the class with finger helpers
    panda.open_fingers = partial(move_fingers, panda=panda, action=FingersAction.OPEN)
    panda.close_fingers = partial(move_fingers, panda=panda, action=FingersAction.CLOSE)

    # Add a custom joint controller to the panda
    add_panda_controller(panda=panda, controller_period=gazebo.step_size())

    # Populate the world
    table = insert_table(world=world)
    bucket = insert_bucket(world=world)
    gazebo.run(paused=True)

    # Create and configure IK for the panda
    ik_joints = [
        j.name() for j in panda.joints() if j.type is not scenario_core.JointType_fixed
    ]
    ik = get_panda_ik(panda=panda, optimized_joints=ik_joints)

    # Get some manipulator links
    finger_left = panda.get_link(link_name="panda_leftfinger")
    finger_right = panda.get_link(link_name="panda_rightfinger")
    end_effector_frame = panda.get_link(link_name="end_effector_frame")

    while True:

        # Insert a new cube
        cube = insert_cube_in_operating_area(world=world)
        gazebo.run(paused=True)

        # =========================
        # PHASE 1: Go over the cube
        # =========================

        print("Hovering")

        # Position over the cube
        position_over_cube = np.array(cube.base_position()) + np.array([0, 0, 0.4])

        # Get the joint configuration that brings the EE over the cube
        over_joint_configuration = solve_ik(
            target_position=position_over_cube,
            target_orientation=np.array(cube.base_orientation()),
            ik=ik,
        )

        # Set the joint references
        assert panda.set_joint_position_targets(over_joint_configuration, ik_joints)

        # Open the fingers
        panda.open_fingers()

        # Run the simulation until the EE reached the desired position
        while not end_effector_reached(
            position=position_over_cube,
            end_effector_link=end_effector_frame,
            max_error_pos=0.05,
            max_error_vel=0.5,
        ):
            gazebo.run()

        # Wait a bit more
        [gazebo.run() for _ in range(500)]

        # =======================
        # PHASE 2: Reach the cube
        # =======================

        print("Reaching")

        # Get the joint configuration that brings the EE to the cube
        over_joint_configuration = solve_ik(
            target_position=np.array(cube.base_position()) + np.array([0, 0, 0.04]),
            target_orientation=np.array(cube.base_orientation()),
            ik=ik,
        )

        # Set the joint references
        assert panda.set_joint_position_targets(over_joint_configuration, ik_joints)
        panda.open_fingers()

        # Run the simulation until the EE reached the desired position
        while not end_effector_reached(
            position=np.array(cube.base_position()) + np.array([0, 0, 0.04]),
            end_effector_link=end_effector_frame,
        ):

            gazebo.run()

        # Wait a bit more
        [gazebo.run() for _ in range(500)]

        # =======================
        # PHASE 3: Grasp the cube
        # =======================

        print("Grasping")

        # Close the fingers
        panda.close_fingers()

        # Detect a graps reading the contact wrenches of the finger links
        while not (
            np.linalg.norm(finger_left.contact_wrench()) >= 50.0
            and np.linalg.norm(finger_right.contact_wrench()) >= 50.0
        ):
            gazebo.run()

        # =============
        # PHASE 4: Lift
        # =============

        print("Lifting")

        # Position over the cube
        position_over_cube = np.array(cube.base_position()) + np.array([0, 0, 0.4])

        # Get the joint configuration that brings the EE over the cube
        over_joint_configuration = solve_ik(
            target_position=position_over_cube,
            target_orientation=np.array(cube.base_orientation()),
            ik=ik,
        )

        # Set the joint references
        assert panda.set_joint_position_targets(over_joint_configuration, ik_joints)

        # Run the simulation until the EE reached the desired position
        while not end_effector_reached(
            position=position_over_cube,
            end_effector_link=end_effector_frame,
            max_error_pos=0.1,
            max_error_vel=0.5,
        ):
            gazebo.run()

        # Wait a bit more
        [gazebo.run() for _ in range(500)]

        # =====================================
        # PHASE 5: Place the cube in the bucket
        # =====================================

        print("Dropping")

        # Get the joint configuration that brings the EE over the bucket
        unload_joint_configuration = solve_ik(
            target_position=get_unload_position(bucket=bucket),
            target_orientation=np.array([0, 1.0, 0, 0]),
            ik=ik,
        )

        # Set the joint references
        assert panda.set_joint_position_targets(unload_joint_configuration, ik_joints)

        # Run the simulation until the EE reached the desired position
        while not end_effector_reached(
            position=get_unload_position(bucket=bucket)
            + np.random.uniform(low=-0.05, high=0.05, size=3),
            end_effector_link=end_effector_frame,
            max_error_pos=0.01,
            max_error_vel=0.1,
            mask=np.array([1, 1, 0]),
        ):

            gazebo.run()

        # Open the fingers
        panda.open_fingers()

        # Wait that both fingers are in not contact (with the cube)
        while finger_left.in_contact() or finger_right.in_contact():
            gazebo.run()

        # Wait a bit more
        [gazebo.run() for _ in range(500)]

        # Remove the cube
        world.remove_model(model_name=cube.name())

    # It is always a good practice to close the simulator.
    # In this case it is not required since above there is an infinite loop.
    # gazebo.close()


================================================
FILE: docs/sphinx/getting_started/scenario.rst
================================================
.. _getting_started_scenario:

ScenarIO
========

In this getting started section we show how to use the Gazebo ScenarIO library to simulate a pendulum system.
We will use the models of the ground plane and the pendulum stored in the repository
`gym_ignition_models <https://github.com/robotology/gym-ignition-models>`_.

The final outcome of this section is shown in the following GIF:

.. figure:: https://user-images.githubusercontent.com/469199/99263551-a9097a80-281f-11eb-98de-714c69385b06.png
   :align: center

.. tip::
    We fully support `Ignition Fuel <https://app.ignitionrobotics.org/dashboard>`_, a constantly enlarging database of SDF models.
    You can use :py:meth:`~scenario.bindings.gazebo.get_model_file_from_fuel` to download any model of the database:

    .. code-block:: python

      from scenario import gazebo as scenario_gazebo

      model_name = "Electrical Box"

      model_file = scenario_gazebo.get_model_file_from_fuel(
          uri=f"https://fuel.ignitionrobotics.org/openrobotics/models/{model_name}")

.. _getting_started_scenario_python:

Python
******

.. tabs::
  .. group-tab:: example.py

    .. code-block:: python

      import time
      import gym_ignition_models
      from scenario import gazebo as scenario_gazebo

      # Create the simulator
      gazebo = scenario_gazebo.GazeboSimulator(step_size=0.001,
                                               rtf=1.0,
                                               steps_per_run=1)

      # Initialize the simulator
      gazebo.initialize()

      # Get the default world and insert the ground plane
      world = gazebo.get_world()
      world.insert_model(gym_ignition_models.get_model_file("ground_plane"))

      # Select the physics engine
      world.set_physics_engine(scenario_gazebo.PhysicsEngine_dart)

      # Open the GUI
      gazebo.gui()
      time.sleep(3)
      gazebo.run(paused=True)

      # Insert a pendulum
      world.insert_model(gym_ignition_models.get_model_file("pendulum"))
      gazebo.run(paused=True)
      time.sleep(3)

      # Get the pendulum model
      pendulum = world.get_model("pendulum")

      # Reset the pole position
      pendulum.get_joint("pivot").to_gazebo().reset_position(0.01)
      gazebo.run(paused=True)
      time.sleep(3)

      # Simulate 30 seconds
      for _ in range(int(30.0 / gazebo.step_size())):
          gazebo.run()

      # Close the simulator
      time.sleep(5)
      gazebo.close()

.. _getting_started_scenario_cpp:

C++
***

.. tabs::
  .. group-tab:: example.cpp

    .. code-block:: cpp

      #include <scenario/gazebo/GazeboSimulator.h>
      #include <scenario/gazebo/Joint.h>
      #include <scenario/gazebo/Model.h>
      #include <scenario/gazebo/World.h>

      #include <chrono>
      #include <string>
      #include <thread>

      int main(int argc, char* argv[])
      {
          // Create the simulator
          auto gazebo = scenario::gazebo::GazeboSimulator(
              /*stepSize=*/0.001, /*rtf=*/1.0, /*stepsPerRun=*/1);

          // Initialize the simulator
          gazebo.initialize();

          // Get the default world
          auto world = gazebo.getWorld();

          // Insert the ground plane
          const std::string groundPlaneSDF = "ground_plane.sdf";
          world->insertModel(groundPlaneSDF);

          // Select the physics engine
          world->setPhysicsEngine(scenario::gazebo::PhysicsEngine::Dart);

          // Open the GUI
          gazebo.gui();
          std::this_thread::sleep_for(std::chrono::seconds(3));
          gazebo.run(/*paused=*/true);

          // Insert a pendulum
          const std::string pendulumURDF = "pendulum.urdf";
          world->insertModel(/*modelFile=*/pendulumURDF);
          gazebo.run(/*paused=*/true);

          // Get the pendulum
          auto pendulum = world->getModel(/*modelName=*/"pendulum");

          // Reset the pole position
          auto pivot = pendulum->getJoint("pivot");
          auto pivotGazebo = std::static_pointer_cast<scenario::gazebo::Joint>(pivot);
          pivotGazebo->resetPosition(0.001);

          // Simulate 30 seconds
          for (size_t i = 0; i < 30.0 / gazebo.stepSize(); ++i) {
              gazebo.run();
          }

          // Close the simulator
          std::this_thread::sleep_for(std::chrono::seconds(3));
          gazebo.close();

          return 0;
      }

  .. group-tab:: CMakeLists.txt

    .. code-block:: cmake

      cmake_minimum_required(VERSION 3.16)
      project(ExampleWithScenario VERSION 1.0)

      set(CMAKE_CXX_STANDARD 17)
      set(CMAKE_CXX_STANDARD_REQUIRED ON)

      find_package(Scenario COMPONENTS Gazebo REQUIRED)

      add_executable(ExampleWithScenario example.cpp)

      target_link_libraries(ExampleWithScenario PRIVATE
          ScenarioGazebo::ScenarioGazebo
          ScenarioGazebo::GazeboSimulator)

.. note::

    The environment should be properly configured to find the plugins and the models.
    Use ``IGN_GAZEBO_SYSTEM_PLUGIN_PATH`` for the plugins and ``IGN_GAZEBO_RESOURCE_PATH`` for the models and meshes.


================================================
FILE: docs/sphinx/index.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <title>Redirecting to master branch</title>
    <meta charset="utf-8">
    <meta http-equiv="refresh" content="0; url=./master/index.html">
    <link rel="canonical" href="https://robotology.github.io/gym-ignition/master/index.html">
  </head>
</html>


================================================
FILE: docs/sphinx/index.rst
================================================
.. _scenario_and_gym_ignition:

ScenarIO and gym-ignition
=========================

This project targets both *control* and *robot learning* research domains:

- Researchers in robotics and control can simulate their robots with familiar tools like Gazebo and URDF/SDF,
  without the need to rely on any middleware.
- Researchers in robot learning can quickly develop new robotic environments that can scale to hundreds of parallel instances.

We provide two related subprojects to each of these categories:

1. **ScenarIO** provides APIs to interface with the robots.
2. **gym-ignition** helps structuring environments compatible with OpenAI Gym,
   while minimizing boilerplate code and providing common rigid-body dynamics utilities.

Check the sections :ref:`What is ScenarIO <what_is_scenario>` and
:ref:`What is gym-ignition <what_is_gym_ignition>` for more details,
and visit :ref:`Motivations <motivations>` for an extended overview.

For a quick practical introduction, visit the :ref:`Getting Started <getting_started_scenario>` page.

If you use this project for your research, please check the FAQ about :ref:`how to give credit <faq_citation>`.

.. list-table::

   * - |pendulum_swing|
     - |panda_grasping|
     - |icub_stepping|

.. |icub_stepping| image:: https://user-images.githubusercontent.com/469199/99262746-9e021a80-281e-11eb-9df1-d70134b0801a.png
.. |panda_grasping| image:: https://user-images.githubusercontent.com/469199/99263111-0cdf7380-281f-11eb-9cfe-338b2aae0503.png
.. |pendulum_swing| image:: https://user-images.githubusercontent.com/469199/99262383-321fb200-281e-11eb-89cc-cc31f590daa3.png

.. toctree::
   :hidden:
   :maxdepth: 1
   :caption: What

   what/what_is_scenario
   what/what_is_gym_ignition

.. toctree::
   :hidden:
   :maxdepth: 1
   :caption: Why

   why/motivations
   why/why_scenario
   why/why_ignition_gazebo
   why/why_gym_ignition

.. toctree::
   :hidden:
   :maxdepth: 1
   :caption: Installation (How)

   installation/support_policy
   installation/stable
   installation/nightly
   installation/developer

.. toctree::
   :hidden:
   :maxdepth: 1
   :caption: Getting Started

   getting_started/scenario
   getting_started/manipulation
   getting_started/gym-ignition

.. toctree::
   :hidden:
   :maxdepth: 2
   :caption: ScenarIO C++ API:

   breathe/core
   breathe/gazebo

.. toctree::
   :hidden:
   :maxdepth: 2
   :caption: Python Packages

   apidoc/scenario/scenario.bindings
   apidoc/gym-ignition/gym_ignition
   apidoc/gym-ignition-environments/gym_ignition_environments

.. toctree::
   :hidden:
   :maxdepth: 2
   :caption: Information

   info/faq
   info/limitations


================================================
FILE: docs/sphinx/info/faq.rst
================================================
FAQ
===

.. _faq_citation:

How to give credit?
-------------------

If you use **ScenarIO** or **gym-ignition** for your research,
please cite the following reference:

.. code-block:: bibtex
   :caption: BibTeX entry

   @INPROCEEDINGS{ferigo2020gymignition,
     title={Gym-Ignition: Reproducible Robotic Simulations for Reinforcement Learning},
     author={D. {Ferigo} and S. {Traversaro} and G. {Metta} and D. {Pucci}},
     booktitle={2020 IEEE/SICE International Symposium on System Integration (SII)},
     year={2020},
     pages={885-890},
     doi={10.1109/SII46433.2020.9025951}
   }

Interaction with Tensorflow
---------------------------

If your Python application imports both ``scenario`` and ``tensorflow``,
you might experience segfaults with no error messages.
Likely the problem is the `protobuf <https://github.com/protocolbuffers/protobuf>`_ library.
In fact, both Tensorflow and Ignition Gazebo link agains protobuf, but while Gazebo uses the
default version of your OS, Tensorflow vendors a more recent version.
If you import ``scenario`` before ``tensorflow``, the system protobuf is loaded, and
Tensorflow will segfault.

The only workaround we found is importing Tensorflow first:

>>> import tensorflow
>>> import scenario.bindings.gazebo

Ogre2 and OpenGL
----------------

On GNU/Linux distributions that ship an old OpenGL version, the GUI could fail to open printing
error like *Unable to create the rendering window*.
The reason is that Ignition Gazebo has `ogre-next <https://github.com/OGRECave/ogre-next>`_
(also known as ogre2) as default rendering engine, and it requires OpenGL greater than 3.3.
You can find more details `here <https://github.com/ignitionrobotics/docs/blob/master/fortress/troubleshooting.md#unable-to-create-the-rendering-window>`_.

The workaround we recommend is modifying the file ``~/.ignition/gazebo/gui.config`` as follows:

.. code-block:: diff

   --- .ignition/gazebo/gui.config 2020-06-04 14:41:33.471804733 +0200
   +++ .ignition/gazebo/gui.config 2020-06-04 14:42:47.826475035 +0200
   @@ -30,7 +30,7 @@
        <property type='bool' key='showTitleBar'>false</property>
        <property type='string' key='state'>docked</property>
      </ignition-gui>
   -  <engine>ogre2</engine>
   +  <engine>ogre</engine>
      <scene>scene</scene>
      <ambient_light>0.4 0.4 0.4</ambient_light>
      <background_color>0.8 0.8 0.8</background_color>

After this modification, world SDF files that do no specifically ask ``ogre2`` will use
``ogre`` as default rendering engine which works also with older OpenGL versions.

Default SDF world
-----------------

If not specified differently, the :cpp:class:`~scenario::gazebo::GazeboSimulator`
class uses a default world file that is completely empty, without even the ground plane.
You can load a custom SDF world using :cpp:func:`~scenario::gazebo::GazeboSimulator::insertWorldFromSDF()` and then
extracting it from the simulator with :cpp:func:`~scenario::gazebo::GazeboSimulator::getWorld()` using its name.

.. code-block:: xml
   :caption: ``empty.world``: use this file as starting point for your custom world

   <?xml version="1.0" ?>
   <sdf version="1.7">
       <world name="default">
           <physics default="true" type="ignored">
           </physics>
           <light type="directional" name="sun">
               <cast_shadows>true</cast_shadows>
               <pose>0 0 10 0 0 0</pose>
               <diffuse>0.8 0.8 0.8 1</diffuse>
               <specular>0.2 0.2 0.2 1</specular>
               <attenuation>
                   <range>1000</range>
                   <constant>0.9</constant>
                   <linear>0.01</linear>
                   <quadratic>0.001</quadratic>
               </attenuation>
               <direction>-0.5 0.1 -0.9</direction>
           </light>
       </world>
   </sdf>

.. note::

   If you don't specify any GUI configuration, the default ``~/.ignition/gazebo/gui.config`` is used.
   This is the preferred approach since it's easier to maintain and keep world files updated.
   You can find more information in the upstream `default.sdf <https://github.com/ignitionrobotics/ign-gazebo/blob/master/examples/worlds/default.sdf>`_.

.. tip::

   You don't need to add the physics plugin in the world file. You can use
   :cpp:func:`scenario::gazebo::World::setPhysicsEngine()` from your code.
   You can also load other plugins during runtime using
   :cpp:func:`scenario::gazebo::World::insertWorldPlugin()` and
   :cpp:func:`scenario::gazebo::Model::insertModelPlugin()`.


================================================
FILE: docs/sphinx/info/limitations.rst
================================================
Limitations
===========

Sensors support
---------------

Ignition Gazebo supports a wide variety of `sensors <https://ignitionrobotics.org/docs/citadel/comparison#sensors>`_,
like cameras, lidars, ...
However, ScenarI/O and consequently gym-ignition are not yet able to extract data from sensors.
Follow :issue:`199` if you're interested in sensors support.

Performance
-----------

When operating on a single model, DART provides good enough performance and accuracy for most of the use-cases.
However, we noticed that it does not perform well when many models are inserted in the simulated world,
especially in contact-rich scenarios.

If your aim is performing simulations for robot learning, we recommend running multiple instances of the simulator,
each of them operating on a world containing a single robot.

If your aim is simulating a big world where the controlled model can move inside the scene, exploiting a new feature
of Ignition Gazebo called `levels <https://github.com/ignitionrobotics/ign-gazebo/blob/ign-gazebo4/tutorials/levels.md>`_
could be the proper solution. This feature is exploited by the big worlds of `subt <https://subtchallenge.com>`_.

Instead, if your world has many models and the usage of levels does not apply to your use-case, you can try to switch
the physics backend to an engine that handles better your simulation.

.. note::

   At the time of writing only DART is officially supported.
   There is some recent activity to implement the bullet physics engine, but this back-and is not yet ready.
   As last resort, you can implement a new physics backend following the
   `instructions <https://github.com/ignitionrobotics/ign-physics/blob/ign-physics3/tutorials/03_physics_plugins.md>`_.


================================================
FILE: docs/sphinx/installation/developer.rst
================================================
.. _installation_developer:

Developer Installation
======================

This installation type is intended for those that want to contribute to the development of the project.
Compared to :ref:`Stable <installation_stable>` and :ref:`Nightly <installation_nightly>`,
this installation type provides a simplified setup for development, VCS integration, and debugging.

Depending on whether you want to target the ``Stable`` or ``Nightly`` channels,
you have to clone respectively the ``master`` or ``devel`` branch.
Check our :ref:`support policy <support_policy>` to select the right distribution of Ignition to install.

Dependencies
************

The developer installation requires finding in the system other dependencies not required by the other installation types.
In those cases, we rely on setuptools to download, install, and find all the necessary third-party dependencies.

1. **iDynTree**: ``gym_ignition`` provides helper classes to manipulate the kinematics and the dynamics of rigid-bodies.
   Among the many existing solutions, we selected the algorithms implemented in `iDynTree <https://github.com/robotology/idyntree/>`_.

   Follow the `official installation instructions <https://github.com/robotology/idyntree/#installation>`__ and make sure
   that you also enable and install the `Python bindings <https://github.com/robotology/idyntree/#bindings>`__.

   You can verify that the installation succeeded and your system is properly configured if you can ``import idyntree.bindings`` in a Python interpreter.

C++ Project
***********

From the root of the repository and from the branch you are interested, you can configure, compile, and install
the CMake project as follows:

.. code-block:: bash

    cd scenario/
    cmake -S . -B build
    cmake --build build/
    cmake --build build/ --target install

.. note::

    The default install prefix of the CMake project is ``/usr/local``.
    If you want to use a different folder, pass ``-DCMAKE_INSTALL_PREFIX=/new/install/prefix`` to the first ``cmake`` command.

.. attention::

    The SWIG bindings are installed in the `site-packages <https://docs.python.org/3/install/#how-installation-works>`_
    folder of the active Python interpreter.
    If you have an active virtual environment, it will be automatically detected.
    We rely on CMake's logic for detecting Python,
    visit `FindPython3 <https://cmake.org/cmake/help/v3.16/module/FindPython3.html>`_ for more details.

.. include:: virtual_environment.rst

Editable Python Installation
****************************

Install the Python package in `editable mode <https://pip.pypa.io/en/stable/reference/pip_install/#editable-installs>`_.
From the root of the repository:

.. code-block:: bash

    pip install -e scenario/
    pip install -e .

The editable installation only symlinks the resources of the repository into the active Python installation.
It allows to develop directly operating on the files of the repository and use the updated package without requiring
to install it again.

.. note::

    The ``scenario`` editable installation is just a placeholder.
    It is necessary to prevent the editable installation of ``gym-ignition`` to override the resources installed by
    the manual CMake execution.
    Otherwise, the ``scenario`` package from PyPI would be pulled, resulting with a wrong version.

.. include:: system_configuration.rst


================================================
FILE: docs/sphinx/installation/nightly.rst
================================================
.. _installation_nightly:

Nightly
=======

The nightly channel contains the most recent updates of the project.
As described in the :ref:`support policy <support_policy>`, this channel requires building Ignition from sources.

We publish updated nightly packages after any pull request merged in the ``devel`` branch.

.. include:: virtual_environment.rst

PyPI Package
************

We provide two different packages for ScenarIO and gym-ignition.

If you are interested in the ScenarIO package,
install the `scenario <https://pypi.org/project/scenario/>`_ package from PyPI:

.. code-block:: bash

   pip install --pre scenario

Instead, if you are interested in gym-ignition,
install the `gym-ignition <https://pypi.org/project/gym-ignition/>`_ package from PyPI:

.. code-block:: bash

   pip install --pre scenario gym-ignition

Note that in this case, specifying also the ``scenario`` dependency is necessary,
otherwise ``pip`` will pull the stable package from PyPI.

.. include:: system_configuration.rst


================================================
FILE: docs/sphinx/installation/stable.rst
================================================
.. _installation_stable:

Stable
======

The stable channel is the easiest way to setup your system.
As described in the :ref:`support policy <support_policy>`, this channel allows installing Ignition from binary packages.

We publish updated stable packages after any tagged release of the ``master`` branch.

.. include:: virtual_environment.rst

PyPI Package
************

We provide two different packages for ScenarIO and gym-ignition.

If you are interested in the ScenarIO package,
install the `scenario <https://pypi.org/project/scenario/>`_ package from PyPI:

.. code-block:: bash

   pip install scenario

Instead, if you are interested in gym-ignition,
install the `gym-ignition <https://pypi.org/project/gym-ignition/>`_ package from PyPI:

.. code-block:: bash

   pip install gym-ignition

It will download and install also ``scenario`` since it depends on it.


================================================
FILE: docs/sphinx/installation/support_policy.rst
================================================
.. _support_policy:

Support policy
==============

**gym-ignition** is an hybrid C++ and Python project and it requires finding in the system updated compile and runtime
dependencies, depending on the installation type you select.

The project mostly supports all the major operating systems.
However, we are currently using and testing only GNU/Linux systems.
We do not yet provide official support to other operating systems.

The table below recaps the project requirements of the :ref:`Stable <installation_stable>` and :ref:`Nightly <installation_nightly>` channels:

+-------------+-----------------+--------+----------------------+----------+------------+---------+
| Channel     |       C++       | Python |      Ignition        |  Ubuntu  | macOS [*]_ | Windows |
+=============+=================+========+======================+==========+============+=========+
| **Stable**  | >= gcc8, clang6 | >= 3.8 | `Fortress`_ (binary) | >= 20.04 |     No     |    No   |
+-------------+-----------------+--------+----------------------+----------+------------+---------+
| **Nightly** | >= gcc8, clang6 | >= 3.8 | `Fortress`_ (source) | >= 20.04 |     No     |    No   |
+-------------+-----------------+--------+----------------------+----------+------------+---------+

.. _`Fortress`: https://ignitionrobotics.org/docs/fortress/install

.. [*] Ignition officially supports macOS and also ``gym-ignition`` could be installed on this platform.
       However, we do not currently test this configuration and we cannot guarantee support.

.. important::

    Our policy is to support Ubuntu from the most recent LTS distribution, currently Ubuntu 20.04 Focal.
    We typically switch to a new LTS when the first minor release ``YY.MM.1`` is released.

    The Python and compilers policies follow a similar approach, we try to keep them updated as much as
    possible following what the supported LTS distribution includes.

.. note::

    External contributions to extend the support and provide feedback about other platforms are most welcome.

.. admonition:: Fun fact

    In the same spirit of `ubuntu/+bug/1 <https://bugs.launchpad.net/ubuntu/+bug/1>`_, we have our own :issue:`1`.


================================================
FILE: docs/sphinx/installation/system_configuration.rst
================================================
System Configuration
********************

This section applies only to the installations that require building Ignition from sources.

If you installed Ignition from sources, you likely used ``colcon`` and therefore the entire suite was installed in a custom folder called workspace.
The workspace contains all the shared libraries and executables of Ignition, including the plugins loaded during runtime.
Since we cannot know in advance where you created the workspace, ``gym-ignition`` is not able to find the physics plugins.

After you enabled the workspace by sourcing its bash script, you may need to also export the following variable:

.. code-block:: bash

   export IGN_GAZEBO_PHYSICS_ENGINE_PATH=${IGN_GAZEBO_PHYSICS_ENGINE_PATH}:${COLCON_PREFIX_PATH}/lib/ign-physics-3/engine-plugins/

Make sure to select the folder corresponding to the correct version of ign-physics, otherwise the wrong plugins are found.


================================================
FILE: docs/sphinx/installation/virtual_environment.rst
================================================
Virtual Environment (optional)
******************************

This step is optional but highly recommended.
Visit the `virtual environments <https://docs.python.org/3.6/tutorial/venv.html>`_ documentation for more details.

.. code-block:: bash

   sudo apt install virtualenv
   virtualenv -p python3.8 $HOME/venv
   source $HOME/venv/bin/activate

Note that the activation is temporary and it is valid only in the same terminal.
Make sure to execute the next steps in a terminal where the virtual environment is active.


================================================
FILE: docs/sphinx/what/what_is_gym_ignition.rst
================================================
.. _what_is_gym_ignition:

What is gym-ignition?
=====================

**gym-ignition** is a framework to create **reproducible robotics environments** for reinforcement learning research.

It is based on the :ref:`ScenarIO <what_is_scenario>` project which provides the low-level APIs to interface with the Ignition Gazebo simulator.
By default, RL environments share a lot of boilerplate code, e.g. for initializing the simulator or structuring the classes
to expose the ``gym.Env`` interface.
Gym-ignition provides the :py:class:`~gym_ignition.base.task.Task` and :py:class:`~gym_ignition.base.runtime.Runtime`
abstractions that help you focusing on the development of the decision-making logic rather than engineering.
It includes :py:mod:`~gym_ignition.randomizers` to simplify the implementation of domain randomization
of models, physics, and tasks.
Gym-ignition also provides powerful dynamics algorithms compatible with both fixed-base and floating-based robots by
exploiting `iDynTree <https://github.com/robotology/idyntree/>`_ and exposing
high-level functionalities (:py:mod:`~gym_ignition.rbd.idyntree`).

Gym-ignition does not provide out-of-the-box environments ready to be used.
Rather, its aim is simplifying and streamlining their development.
Nonetheless, for illustrative purpose, it includes canonical examples in the
:py:mod:`gym_ignition_environments` package.


================================================
FILE: docs/sphinx/what/what_is_scenario.rst
================================================
.. _what_is_scenario:

What is ScenarIO
================

**ScenarIO** is a C++ abstraction layer to interact with simulated and real robots.

It mainly provides the following
`C++ interfaces <https://github.com/robotology/gym-ignition/tree/master/scenario/core/include/scenario/core>`_:

- :cpp:class:`scenario::core::World`
- :cpp:class:`scenario::core::Model`
- :cpp:class:`scenario::core::Link`
- :cpp:class:`scenario::core::Joint`

These interfaces can be implemented to operate on different scenarios,
including robots operating on either simulated worlds or in real-time.

ScenarIO currently fully implements **Gazebo ScenarIO** (APIs),
a simulated back-end that interacts with `Ignition Gazebo <https://ignitionrobotics.org>`_.
The result allows stepping the simulator programmatically, ensuring a fully reproducible behaviour.
It relates closely to other projects like
`pybullet <https://github.com/bulletphysics/bullet3>`_ and `mujoco-py <https://github.com/openai/mujoco-py>`_.

A real-time backend that interacts with the `YARP <https://github.com/robotology/yarp>`_ middleware is under development.

ScenarIO can be used either from C++ (:ref:`Core APIs <scenario_core>`, :ref:`Gazebo APIs <scenario_gazebo>`)
or from Python (:py:mod:`~scenario.bindings.core`, :py:mod:`~scenario.bindings.gazebo`).

If you're interested to know the reasons why we started developing ScenarIO and why we selected Ignition Gazebo
for our simulations, visit the :ref:`Motivations <motivations>` section.


================================================
FILE: docs/sphinx/why/motivations.rst
================================================
.. _motivations:

Intro
=====

In this section we recap the motivations behind this project.
Choosing the right framework for your research is often challenging and we hope to provide a broader look that could
help deciding whether it meets your needs or not.

The development of the framework is evolving quickly, and the architecture and motivations described in the
:ref:`reference publication <faq_citation>` are becoming outdated.
While that publication remains the reference in case you use the project for your research,
this section provides a constantly updated description aligned with the most recent development news.


================================================
FILE: docs/sphinx/why/why_gym_ignition.rst
================================================
.. _why_gym_ignition:

Why gym-ignition
================

In the previous sections we described why we developed ScenarIO and why we used Ignition Gazebo to implement its simulation back-end.
While we mentioned few advantages for the robot learning domain, ScenarIO remains a general C++ library that can be used for generic robotic applications.

The reinforcement learning community, in the past years, converged towards Python for the development of the environments
containing the decision-making logic.
`OpenAI Gym <https://gym.openai.com>`_ became the reference interface to provide a clear separation between agents and environments.
A widespread interface is powerful because if you implement an environment that exposes the ``gym.Env`` interface, you can then use
all the countless frameworks provided by the community to train a policy selecting your favourite algorithm.

The Python package ``gym_ignition`` enables you to create robotic environments compatible with OpenAI Gym.
Being based on ScenarIO, it enables to develop environments that can run not only on different physics engines,
but also on real robots.

You can think of ``gym_ignition`` as a way to help you structuring your environment.
If you know how `pytorch-lightning <https://github.com/PyTorchLightning/pytorch-lightning>`_ relates to PyTorch,
the same applies to the interaction between gym-ignition and ScenarIO.
Thanks to the :py:class:`~gym_ignition.base.task.Task` and :py:class:`~gym_ignition.base.runtime.Runtime` interfaces,
``gym_ignition`` abstracts away all the unnecessary boilerplate that otherwise you have to copy and paste between environments.

For example, :py:class:`~gym_ignition.runtimes.gazebo_runtime.GazeboRuntime` provides all boilerplate code to take
your implementation of a :py:class:`~gym_ignition.base.task.Task` and simulate it with Ignition Gazebo.

Furthermore, we provide useful classes with functionalities that are commonly required by robotic environments, like
Inverse Kinematic (:py:class:`~gym_ignition.rbd.idyntree.inverse_kinematics_nlp.InverseKinematicsNLP`)
and multibody dynamics algorithms (:py:class:`~gym_ignition.rbd.idyntree.kindyncomputations.KinDynComputations`)
with full support of floating-base systems.

.. note::

   Developing environments for robot learning in C++ is a valid choice and the community has shown different examples.
   ScenarIO can be used to develop C++ environments as well, however we find more useful using Python since it allows
   a faster prototyping.

.. note::

   To the best of our knowledge, the first package that implemented a structure that abstracts the task, the robot, and
   the simulator is `openai_ros <http://wiki.ros.org/openai_ros>`_.
   We have been inspired by its structure in the early stage of development, and the current interfaces implemented in
   gym-ignition are an evolution of the original architecture.


================================================
FILE: docs/sphinx/why/why_ignition_gazebo.rst
================================================
.. _why_ignition_gazebo:

Why Ignition Gazebo
===================

In this section we want to go a bit deeper in the motivations that led us to select Ignition Gazebo as target solution for the simulation back-end of ScenarIO.

To begin, a bit of history. The `Gazebo <https://gazebosim.org>`_ simulator that the entire robotic community has used for
over a decade is different than Ignition Gazebo.
We will refer to the old simulator as Gazebo Classic.
Ignition Gazebo is the new generation of the simulator.
It takes all the lesson learned by the development of Gazebo Classic and provides a more modular and extensible framework for robotic simulations.
The monolithic structure of Gazebo Classic has been broken in standalone libraries, obtaining a *suite* called `Ignition <https://ignitionrobotics.org>`_.
Ignition Gazebo is just one of the libraries [*]_ that compose the suite.
When we started the development of gym-ignition, Ignition Gazebo was "stable" enough to start using it.
The clear advantage is support: Gazebo Classic will just receive bug fixing, all the development effort now shifted towards the new Ignition Gazebo.
The price to pay, instead, is that Ignition Gazebo has not yet reached feature parity with Gazebo Classic, even though
the gap is getting filled quickly.

.. [*] Yes, you read correctly: *library*. Ignition Gazebo is a library.
       A ``ignition::gazebo::Server`` object can be instantiated and it can be stepped programmatically from your code.
       This type of architecture became quite popular recently because it gives you full control of the simulation.
       Ignition Gazebo, therefore, became a solution similar to the well known alternatives like ``pybullet`` and ``mujoco-py``.

We have been and currently are Gazebo Classic users, as many other robotics research labs.
Over time, we became familiar with the tools and methods of Gazebo Classic and built a lot of code and applications that depend on it.
Unfortunately, despite someone has shown attempts, Gazebo Classic is not suitable for the large-scale simulations that are
typical in modern reinforcement learning architectures.
Ignition Gazebo offered us a viable solution for this use case that allows us to exploit the know-how we gained with Gazebo Classic.

The two main features that drove us towards the adoption of Ignition Gazebo are the following:

1. **Physics engines are loaded as plugin libraries and Ignition Gazebo operates on an API-stable interface.**
   This architecture allows everyone to implement a new physics engine backend and run simulations exploiting all the other
   components of the Ignition suite (rendering, systems, ...).
   While today only `DART <https://github.com/dartsim/dart>`_ is officially supported, we believe this is one of the best
   attempts to obtain in the long run a framework that allows to switch physics engines with minimal effort.
   For reinforcement learning research, it could bring domain randomization to the next level.
2. **Simulations can be stepped programmatically without relying on network transport, guaranteeing full reproducibility.**
   Reproducible simulations are paramount whether you are prototyping a new robot controller or you are running
   large-scale simulations for robot learning.
   Most of the client-server architectures cannot guarantee reproducibility since asynchronous network transports could
   provide different results depending on the load of your system.
   An effective solution is using the simulator as a library and stepping it programmatically from your code.
   Gazebo ScenarIO provides APIs to perform these kind of simulations with Ignition Gazebo.

There are a bunch of other nice features we didn't cover in this section.
Not all of them are currently exposed to ScenarIO Gazebo, please open a feature request if you have any suggestion or,
even better, fire up a pull request!

To summarize, these are the features that motivated us to choose Ignition Gazebo:

- Simulator developed for robotics
- Simulator-as-a-library structure
- Abstraction of different physics engines and rendering engines
- Modular software architecture
- Powerful and constantly improving SDF model description
- Well maintained, packaged, and widely tested
- Large big database of objects to create worlds: `Ignition Fuel <https://app.ignitionrobotics.org/dashboard>`_
- Long term vision and support

.. note::

   Ignition Gazebo is the target simulator of the new `DARPA Subterranean Challenge <https://subtchallenge.com>`_.
   Have a look to their simulation results to understand what you can expect from using Ignition Gazebo.


================================================
FILE: docs/sphinx/why/why_scenario.rst
================================================
.. _why_scenario:

Why ScenarIO
============

*SCENe interfAces for Robot Input/Output* is an abstraction layer to interface with robots.
It exposes APIs to interact with a scene, providing a :cpp:class:`~scenario::core::World` that can return
:cpp:class:`~scenario::core::Model` objects, from which you can gather measurements and send commands.
The relevant APIs of ScenarIO are documented in the :ref:`Scenario Core <scenario_core>` section.

Many simulators already provide an abstraction of different physics engines.
They expose a unified interface that, after selecting the desired back-end, maps its unified methods to those of the
underlying physics engine. The aim of ScenarIO is extending this idea also to real-time robots.

The simulation backend of ScenarIO communicates with a simulator that itself abstracts physics engines.
This is powerful because, in this way, ScenarIO is independent from the details of the underlying physics engine.
Any current and future physics engine supported by the simulator is compatible with ScenarIO without requiring any
change from our side.

Regarding real-time robots, the APIs of ScenarIO can be implemented exploiting middlewares like ROS or YARP.
At the time of writing there are no official real-time backends, stay tuned for further updates.

Once both the simulation and real-time backends are in place, you can then write code to control your robot just once,
it will interact either with the simulated or the real robot depending on the ScenarIO backend you enabled.

.. note::

   The ScenarIO interface is flexible and generic.
   Let's say you already have built your functionality with the backends we provide,
   and you are not happy from the performance of the simulator we used.
   You can implement your own simulation backend and run it alongside those we provide.
   The same applies to the real-time backend, in case your robot uses a custom middleware or SDK.

.. tip::

   So far, we always referred to the C++ abstraction layer provided by ScenarIO.
   The interface / implementation pattern is implemented with classic inheritance and polymorphism.
   Having such unified interface simplifies the process to expose it to other languages.
   Thanks to SWIG, we officially provide Python bindings of ScenarIO,
   so that you can prototype your applications even faster!


================================================
FILE: examples/panda_pick_and_place.py
================================================
import enum
import time
from functools import partial
from typing import List

import gym_ignition
import gym_ignition_environments
import numpy as np
from gym_ignition.context.gazebo import controllers
from gym_ignition.rbd import conversions
from gym_ignition.rbd.idyntree import inverse_kinematics_nlp
from scipy.spatial.transform import Rotation as R

from scenario import core as scenario_core
from scenario import gazebo as scenario_gazebo

# Configure verbosity
scenario_gazebo.set_verbosity(scenario_gazebo.Verbosity_error)

# Configure numpy output
np.set_printoptions(precision=4, suppress=True)


def add_panda_controller(
    panda: gym_ignition_environments.models.panda.Panda, controller_period: float
) -> None:

    # Set the controller period
    assert panda.set_controller_period(period=controller_period)

    # Increase the max effort of the fingers
    panda.get_joint(
        joint_name="panda_finger_joint1"
    ).to_gazebo().set_max_generalized_force(max_force=500.0)
    panda.get_joint(
        joint_name="panda_finger_joint2"
    ).to_gazebo().set_max_generalized_force(max_force=500.0)

    # Insert the ComputedTorqueFixedBase controller
    assert panda.to_gazebo().insert_model_plugin(
        *controllers.ComputedTorqueFixedBase(
            kp=[100.0] * (panda.dofs() - 2) + [10000.0] * 2,
            ki=[0.0] * panda.dofs(),
            kd=[17.5] * (panda.dofs() - 2) + [100.0] * 2,
            urdf=panda.get_model_file(),
            joints=panda.joint_names(),
        ).args()
    )

    # Initialize the controller to the current state
    assert panda.set_joint_position_targets(panda.joint_positions())
    assert panda.set_joint_velocity_targets(panda.joint_velocities())
    assert panda.set_joint_acceleration_targets(panda.joint_accelerations())


def get_panda_ik(
    panda: gym_ignition_environments.models.panda.Panda, optimized_joints: List[str]
) -> inverse_kinematics_nlp.InverseKinematicsNLP:

    # Create IK
    ik = inverse_kinematics_nlp.InverseKinematicsNLP(
        urdf_filename=panda.get_model_file(),
        considered_joints=optimized_joints,
        joint_serialization=panda.joint_names(),
    )

    # Initialize IK
    ik.initialize(
        verbosity=1,
        floating_base=False,
        cost_tolerance=1e-8,
        constraints_tolerance=1e-8,
        base_frame=panda.base_frame(),
    )

    # Set the current configuration
    ik.set_current_robot_configuration(
        base_position=np.array(panda.base_position()),
        base_quaternion=np.array(panda.base_orientation()),
        joint_configuration=np.array(panda.joint_positions()),
    )

    # Add the cartesian target of the end effector
    end_effector = "end_effector_frame"
    ik.add_target(
        frame_name=end_effector,
        target_type=inverse_kinematics_nlp.TargetType.POSE,
        as_constraint=False,
    )

    return ik


def insert_bucket(world: scenario_gazebo.World) -> scenario_gazebo.Model:

    # Insert objects from Fuel
    uri = lambda org, name: f"https://fuel.ignitionrobotics.org/{org}/models/{name}"

    # Download the cube SDF file
    bucket_sdf = scenario_gazebo.get_model_file_from_fuel(
        uri=uri(
            org="GoogleResearch",
            name="Threshold_Basket_Natural_Finish_Fabric_Liner_Small",
        ),
        use_cache=False,
    )

    # Assign a custom name to the model
    model_name = "bucket"

    # Insert the model
    assert world.insert_model(
        bucket_sdf, scenario_core.Pose([0.68, 0, 1.02], [1.0, 0, 0, 1]), model_name
    )

    # Return the model
    return world.get_model(model_name=model_name)


def insert_table(world: scenario_gazebo.World) -> scenario_gazebo.Model:

    # Insert objects from Fuel
    uri = lambda org, name: f"https://fuel.ignitionrobotics.org/{org}/models/{name}"

    # Download the cube SDF file
    bucket_sdf = scenario_gazebo.get_model_file_from_fuel(
        uri=uri(org="OpenRobotics", name="Table"), use_cache=False
    )

    # Assign a custom name to the model
    model_name = "table"

    # Insert the model
    assert world.insert_model(bucket_sdf, scenario_core.Pose_identity(), model_name)

    # Return the model
    return world.get_model(model_name=model_name)


def insert_cube_in_operating_area(
    world: scenario_gazebo.World,
) -> scenario_gazebo.Model:

    # Insert objects from Fuel
    uri = lambda org, name: f"https://fuel.ignitionrobotics.org/{org}/models/{name}"

    # Download the cube SDF file
    cube_sdf = scenario_gazebo.get_model_file_from_fuel(
        uri=uri(org="openrobotics", name="wood cube 5cm"), use_cache=False
    )

    # Sample a random position
    random_position = np.random.uniform(low=[0.2, -0.3, 1.01], high=[0.4, 0.3, 1.01])

    # Get a unique name
    model_name = gym_ignition.utils.scenario.get_unique_model_name(
        world=world, model_name="cube"
    )

    # Insert the model
    assert world.insert_model(
        cube_sdf, scenario_core.Pose(random_position, [1.0, 0, 0, 0]), model_name
    )

    # Return the model
    return world.get_model(model_name=model_name)


def solve_ik(
    target_position: np.ndarray,
    target_orientation: np.ndarray,
    ik: inverse_kinematics_nlp.InverseKinematicsNLP,
) -> np.ndarray:

    quat_xyzw = R.from_euler(seq="y", angles=90, degrees=True).as_quat()

    ik.update_transform_target(
        target_name=ik.get_active_target_names()[0],
        position=target_position,
        quaternion=conversions.Quaternion.to_wxyz(xyzw=quat_xyzw),
    )

    # Run the IK
    ik.solve()

    return ik.get_reduced_solution().joint_configuration


def end_effector_reached(
    position: np.array,
    end_effector_link: scenario_core.Link,
    max_error_pos: float = 0.01,
    max_error_vel: float = 0.5,
    mask: np.ndarray = np.array([1.0, 1.0, 1.0]),
) -> bool:

    masked_target = mask * position
    masked_current = mask * np.array(end_effector_link.position())

    return (
        np.linalg.norm(masked_current - masked_target) < max_error_pos
        and np.linalg.norm(end_effector_link.world_linear_velocity()) < max_error_vel
    )


def get_unload_position(bucket: scenario_core.Model) -> np.ndarray:

    return bucket.base_position() + np.array([0, 0, 0.3])


class FingersAction(enum.Enum):

    OPEN = enum.auto()
    CLOSE = enum.auto()


def move_fingers(
    panda: gym_ignition_environments.models.panda.Panda, action: FingersAction
) -> None:

    # Get the joints of the fingers
    finger1 = panda.get_joint(joint_name="panda_finger_joint1")
    finger2 = panda.get_joint(joint_name="panda_finger_joint2")

    if action is FingersAction.OPEN:
        finger1.set_position_target(position=finger1.position_limit().max)
        finger2.set_position_target(position=finger2.position_limit().max)

    if action is FingersAction.CLOSE:
        finger1.set_position_target(position=finger1.position_limit().min)
        finger2.set_position_target(position=finger2.position_limit().min)


# ====================
# INITIALIZE THE WORLD
# ====================

# Get the simulator and the world
gazebo, world = gym_ignition.utils.scenario.init_gazebo_sim(
    step_size=0.001, real_time_factor=2.0, steps_per_run=1
)

# Open the GUI
gazebo.gui()
time.sleep(3)
gazebo.run(paused=True)

# Insert the Panda manipulator
panda = gym_ignition_environments.models.panda.Panda(
    world=world, position=[-0.1, 0, 1.0]
)

# Disable joint velocity limits
_ = [j.to_gazebo().set_velocity_limit(1_000) for j in panda.joints()]

# Enable contacts only for the finger links
panda.get_link("panda_leftfinger").to_gazebo().enable_contact_detection(True)
panda.get_link("panda_rightfinger").to_gazebo().enable_contact_detection(True)

# Process model insertion in the simulation
gazebo.run(paused=True)

# Monkey patch the class with finger helpers
panda.open_fingers = partial(move_fingers, panda=panda, action=FingersAction.OPEN)
panda.close_fingers = partial(move_fingers, panda=panda, action=FingersAction.CLOSE)

# Add a custom joint controller to the panda
add_panda_controller(panda=panda, controller_period=gazebo.step_size())

# Populate the world
table = insert_table(world=world)
bucket = insert_bucket(world=world)
gazebo.run(paused=True)

# Create and configure IK for the panda
ik_joints = [
    j.name() for j in panda.joints() if j.type is not scenario_core.JointType_fixed
]
ik = get_panda_ik(panda=panda, optimized_joints=ik_joints)

# Get some manipulator links
finger_left = panda.get_link(link_name="panda_leftfinger")
finger_right = panda.get_link(link_name="panda_rightfinger")
end_effector_frame = panda.get_link(link_name="end_effector_frame")

while True:

    # Insert a new cube
    cube = insert_cube_in_operating_area(world=world)
    gazebo.run(paused=True)

    # =========================
    # PHASE 1: Go over the cube
    # =========================

    print("Hovering")

    # Position over the cube
    position_over_cube = np.array(cube.base_position()) + np.array([0, 0, 0.4])

    # Get the joint configuration that brings the EE over the cube
    over_joint_configuration = solve_ik(
        target_position=position_over_cube,
        target_orientation=np.array(cube.base_orientation()),
        ik=ik,
    )

    # Set the joint references
    assert panda.set_joint_position_targets(over_joint_configuration, ik_joints)

    # Open the fingers
    panda.open_fingers()

    # Run the simulation until the EE reached the desired position
    while not end_effector_reached(
        position=position_over_cube,
        end_effector_link=end_effector_frame,
        max_error_pos=0.05,
        max_error_vel=0.5,
    ):
        gazebo.run()

    # Wait a bit more
    [gazebo.run() for _ in range(500)]

    # =======================
    # PHASE 2: Reach the cube
    # =======================

    print("Reaching")

    # Get the joint configuration that brings the EE to the cube
    over_joint_configuration = solve_ik(
        target_position=np.array(cube.base_position()) + np.array([0, 0, 0.04]),
        target_orientation=np.array(cube.base_orientation()),
        ik=ik,
    )

    # Set the joint references
    assert panda.set_joint_position_targets(over_joint_configuration, ik_joints)
    panda.open_fingers()

    # Run the simulation until the EE reached the desired position
    while not end_effector_reached(
        position=np.array(cube.base_position()) + np.array([0, 0, 0.04]),
        end_effector_link=end_effector_frame,
    ):

        gazebo.run()

    # Wait a bit more
    [gazebo.run() for _ in range(500)]

    # =======================
    # PHASE 3: Grasp the cube
    # =======================

    print("Grasping")

    # Close the fingers
    panda.close_fingers()

    # Detect a graps reading the contact wrenches of the finger links
    while not (
        np.linalg.norm(finger_left.contact_wrench()) >= 50.0
        and np.linalg.norm(finger_right.contact_wrench()) >= 50.0
    ):
        gazebo.run()

    # =============
    # PHASE 4: Lift
    # =============

    print("Lifting")

    # Position over the cube
    position_over_cube = np.array(cube.base_position()) + np.array([0, 0, 0.4])

    # Get the joint configuration that brings the EE over the cube
    over_joint_configuration = solve_ik(
        target_position=position_over_cube,
        target_orientation=np.array(cube.base_orientation()),
        ik=ik,
    )

    # Set the joint references
    assert panda.set_joint_position_targets(over_joint_configuration, ik_joints)

    # Run the simulation until the EE reached the desired position
    while not end_effector_reached(
        position=position_over_cube,
        end_effector_link=end_effector_frame,
        max_error_pos=0.1,
        max_error_vel=0.5,
    ):
        gazebo.run()

    # Wait a bit more
    [gazebo.run() for _ in range(500)]

    # =====================================
    # PHASE 5: Place the cube in the bucket
    # =====================================

    print("Dropping")

    # Get the joint configuration that brings the EE over the bucket
    unload_joint_configuration = solve_ik(
        target_position=get_unload_position(bucket=bucket),
        target_orientation=np.array([0, 1.0, 0, 0]),
        ik=ik,
    )

    # Set the joint references
    assert panda.set_joint_position_targets(unload_joint_configuration, ik_joints)

    # Run the simulation until the EE reached the desired position
    while not end_effector_reached(
        position=get_unload_position(bucket=bucket)
        + np.random.uniform(low=-0.05, high=0.05, size=3),
        end_effector_link=end_effector_frame,
        max_error_pos=0.01,
        max_error_vel=0.1,
        mask=np.array([1, 1, 0]),
    ):

        gazebo.run()

    # Open the fingers
    panda.open_fingers()

    # Wait that both fingers are in not contact (with the cube)
    while finger_left.in_contact() or finger_right.in_contact():
        gazebo.run()

    # Wait a bit more
    [gazebo.run() for _ in range(500)]

    # Remove the cube
    world.remove_model(model_name=cube.name())

# It is always a good practice to close the simulator.
# In this case it is not required since above there is an infinite loop.
# gazebo.close()


================================================
FILE: examples/python/launch_cartpole.py
================================================
# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

import functools
import time

import gym
from gym_ignition.utils import logger
from gym_ignition_environments import randomizers

# Set verbosity
logger.set_level(gym.logger.ERROR)
# logger.set_level(gym.logger.DEBUG)

# Available tasks
env_id = "CartPoleDiscreteBalancing-Gazebo-v0"
# env_id = "CartPoleContinuousBalancing-Gazebo-v0"
# env_id = "CartPoleContinuousSwingup-Gazebo-v0"


def make_env_from_id(env_id: str, **kwargs) -> gym.Env:
    import gym
    import gym_ignition_environments

    return gym.make(env_id, **kwargs)


# Create a partial function passing the environment id
make_env = functools.partial(make_env_from_id, env_id=env_id)

# Wrap the environment with the randomizer.
# This is a simple example no randomization are applied.
env = randomizers.cartpole_no_rand.CartpoleEnvNoRandomizations(env=make_env)

# Wrap the environment with the randomizer.
# This is a complex example that randomizes both the physics and the model.
# env = randomizers.cartpole.CartpoleEnvRandomizer(
#     env=make_env, seed=42, num_physics_rollouts=5)

# Enable the rendering
# env.render('human')

# Initialize the seed
env.seed(42)

for epoch in range(10):

    # Reset the environment
    observation = env.reset()

    # Initialize returned values
    done = False
    totalReward = 0

    while not done:

        # Execute a random action
        action = env.action_space.sample()
        observation, reward, done, _ = env.step(action)

        # Render the environment.
        # It is not required to call this in the loop if physics is not randomized.
        # env.render('human')

        # Accumulate the reward
        totalReward += reward

        # Print the observation
        msg = ""
        for value in observation:
            msg += "\t%.6f" % value
        logger.debug(msg)

    print(f"Reward episode #{epoch}: {totalReward}")

env.close()
time.sleep(5)


================================================
FILE: pyproject.toml
================================================
[build-system]
build-backend = "setuptools.build_meta"
requires = [
    "wheel",
    "setuptools>=45",
    "setuptools_scm[toml]>=6.0",
    "cmake-build-extension",
]

[tool.setuptools_scm]
local_scheme = "dirty-tag"

[tool.black]
line-length = 88

[tool.isort]
profile = "black"
multi_line_output = 3



================================================
FILE: python/gym_ignition/__init__.py
================================================
# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

# Workaround for https://github.com/osrf/sdformat/issues/227.
# It has to be done before loading the bindings.
import gym_ignition_models

gym_ignition_models.setup_environment()

# Add IGN_GAZEBO_RESOURCE_PATH to the default search path
import os

from gym_ignition.utils import resource_finder

if "IGN_GAZEBO_RESOURCE_PATH" in os.environ:
    resource_finder.add_path_from_env_var("IGN_GAZEBO_RESOURCE_PATH")


def initialize_verbosity() -> None:

    import gym
    import gym_ignition.utils.logger

    import scenario

    if scenario.detect_install_mode() is scenario.InstallMode.Developer:
        gym_ignition.utils.logger.set_level(
            level=gym.logger.INFO, scenario_level=gym.logger.WARN
        )

    elif scenario.detect_install_mode() is scenario.InstallMode.User:
        gym_ignition.utils.logger.set_level(
            level=gym.logger.WARN, scenario_level=gym.logger.WARN
        )

    else:
        raise ValueError(scenario.detect_install_mode())


# Configure default verbosity
initialize_verbosity()


================================================
FILE: python/gym_ignition/base/__init__.py
================================================
# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

# Abstract classes
from . import runtime, task


================================================
FILE: python/gym_ignition/base/runtime.py
================================================
# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

import abc

import gym
from gym_ignition.base.task import Task


class Runtime(gym.Env, abc.ABC):
    """
    Base class for defining executors of :py:class:`~gym_ignition.base.task.Task` objects.

    :py:class:`~gym_ignition.base.task.Task` classes are supposed to be generic and are
    not tied to any specific runtime. Implementations of a runtime class contain all the
    logic to define how to execute the task, allowing to run the same
    :py:class:`~gym_ignition.base.task.Task` class on different simulators or in a
    real-time setting.

    Runtimes are the real :py:class:`gym.Env` objects returned to the users when they call
    the :py:class:`gym.make` factory method.

    Args:
        task: the :py:class:`~gym_ignition.base.task.Task` object to handle.
        agent_rate: the rate at which the environment will be called. Sometimes tasks need
            to know this information.

    Example:
        Here is minimal example of how the :py:class:`Runtime`, :py:class:`gym.Env` and
        :py:class:`~gym_ignition.base.task.Task` could be integrated:

    .. code-block:: python

        class FooRuntime(Runtime):

            def __init__(self, task):
                super().__init__(task=task, agent_rate=agent_rate)
                self.action_space, self.observation_space = self.task.create_spaces()

            def reset(self):
                self.task.reset_task()
                return self.task.get_observation()

            def step(self, action):
                self.task.set_action(action)

                # [...] code that performs the real step [...]

                done = self.task.is_done()
                reward = self.task.get_reward()
                observation = self.task.get_observation()

                return observation, reward, done, {}

            def close(self):
                pass

    Note:
        Runtimes can handle only one :py:class:`~gym_ignition.base.task.Task` object.
    """

    def __init__(self, task: Task, agent_rate: float):

        #: Task handled by the runtime.
        self.task: Task = task

        #: Rate of environment execution.
        self.agent_rate = agent_rate

    @abc.abstractmethod
    def timestamp(self) -> float:
        """
        Return the timestamp associated to the execution of the environment.

        In real-time environments, the timestamp is the time read from the host system.
        In simulated environments, the timestamp is the simulated time, which might not
        match the real-time in the case of a real-time factor different than 1.

        Returns:
            The current environment timestamp.
        """


================================================
FILE: python/gym_ignition/base/task.py
================================================
# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

import abc
from typing import Dict, Tuple

import gym
import numpy as np
from gym.utils import seeding
from gym_ignition.utils.typing import (
    Action,
    ActionSpace,
    Observation,
    ObservationSpace,
    Reward,
    SeedList,
)

from scenario import core


class Task(abc.ABC):
    """
    Interface to define a decision-making task.

    The Task is the central interface of each environment implementation.
    It defines the logic of the environment in a format that is agnostic of both the
    runtime (either simulated or real-time) and the models it operates on.

    :py:class:`~gym_ignition.base.runtime.Runtime` instances are the real objects returned
    to the users when they call :py:class:`gym.make`. Depending on the type of the
    runtime, it could contain one or more :py:class:`Task` objects.
    The :py:class:`~gym_ignition.base.runtime.Runtime` is a relay class that calls the
    logic of the :py:class:`Task` from its interface methods and implements the real
    :py:meth:`gym.Env.step`.
    Simulated runtimes step the physics engine, instead, real-time
    runtimes, enforce real-time execution.

    A :py:class:`Task` object is meant to be:

    - Independent from the selected :py:class:`~gym_ignition.base.runtime.Runtime`.
      In fact, it defines only the decision making logic;
    - Independent from the :py:class:`~scenario.core.Model` objects it operates on.
      This is achieved thanks to the model abstraction provided by
      :cpp:class:`scenario::core::Model`.

    The population of the world where the task operates is demanded to a
    :py:class:`gym.Wrapper` object, that acts as an environment randomizer.
    """

    action_space: gym.spaces.Space = None
    observation_space: gym.spaces.Space = None

    def __init__(self, agent_rate: float) -> None:

        # World object
        self._world = None

        #: Rate of the agent.
        #: It matches the rate at which the :py:class:`Gym.Env` methods are called.
        self.agent_rate = agent_rate

        #: RNG available to the object to ensure reproducibility.
        #: Use it for all the random resources.
        self.np_random: np.random.RandomState

        #: The seed of the task
        self.seed: int

        # Initialize the RNG and the seed
        self.np_random, self.seed = seeding.np_random()

    # ==========
    # PROPERTIES
    # ==========

    @property
    def world(self) -> core.World:
        """
        Get the world where the task is operating.

        Returns:
            The world object.
        """

        if self._world is not None:
            return self._world

        raise Exception("The world was never stored")

    @world.setter
    def world(self, world: core.World) -> None:

        if world is None or world.name == "":
            raise ValueError("World not valid")

        # Store the world
        self._world = world

    def has_world(self) -> bool:
        """
        Check if the world was stored.

        Returns:
            True if the task has a valid world, False otherwise.
        """

        return self._world is not None and self._world.name != ""

    # ==============
    # Task Interface
    # ==============

    @abc.abstractmethod
    def create_spaces(self) -> Tuple[ActionSpace, ObservationSpace]:
        """
        Create the action and observations spaces.

        Note:
            This method does not currently have access to the Models part of the
            environment. If the Task is meant to work on different models, we recommend
            using their URDF / SDF model to extract the information you need
            (e.g. number of DoFs, joint position limits, etc). Since actions and
            observations are often normalized, in many cases there's no need to extract
            a lot of information from the model file.

        Raises:
            RuntimeError: In case of failure.

        Returns:
            A tuple containing the action and observation spaces.
        """

    @abc.abstractmethod
    def reset_task(self) -> None:
        """
        Reset the task.

        This method contains the logic for resetting the task.
        It is called in the :py:meth:`gym.Env.reset` method of the corresponding
        environment.

        Raises:
            RuntimeError: In case of failure.
        """

    @abc.abstractmethod
    def set_action(self, action: Action) -> None:
        """
        Set the task action.

        This method contains the logic for setting the environment action.
        It is called in the beginning of the :py:meth:`gym.Env.step` method.

        Args:
            action: The action to set.

        Raises:
            RuntimeError: In case of failure.
        """

    @abc.abstractmethod
    def get_observation(self) -> Observation:
        """
        Return the task observation.

        This method contains the logic for constructing the environment observation.
        It is called in the end of both :py:meth:`gym.Env.reset` and
        :py:meth:`gym.Env.step` methods.

        Raises:
            RuntimeError: In case of failure.

        Returns:
            The task observation.
        """

    @abc.abstractmethod
    def get_reward(self) -> Reward:
        """
        Return the task reward.

        This method contains the logic for computing the environment reward.
        It is called in the end of the :py:meth:`gym.Env.step` method.

        Raises:
            RuntimeError: In case of failure.

        Returns:
            The scalar reward.
        """

    @abc.abstractmethod
    def is_done(self) -> bool:
        """
        Return the task termination flag.

        This method contains the logic for defining when the environment has terminated.
        Subsequent calls to :py:meth:`Task.set_action` should be preceded by a task
        reset through :py:meth:`Task.reset_task`.

        It is called in the end of the :py:meth:`gym.Env.step` method.

        Raises:
            RuntimeError: In case of failure.

        Returns:
            True if the environment terminated, False otherwise.
        """

    def get_info(self) -> Dict:
        """
        Return the info dictionary.

        Returns:
            A ``dict`` with extra information of the task.
        """
        return {}

    def seed_task(self, seed: int = None) -> SeedList:
        """
        Seed the task.

        This method configures the :py:attr:`Task.np_random` RNG.

        Args:
            seed: The seed number.

        Return:
            The list of seeds used by the task.
        """

        # Create the seed if not passed
        seed = np.random.randint(2 ** 32 - 1) if seed is None else seed

        # Get an instance of the random number generator from gym utils.
        # This is necessary to have an independent rng for each environment.
        self.np_random, self.seed = seeding.np_random(seed)

        # Seed the spaces
        self.action_space.seed(self.seed)
        self.observation_space.seed(self.seed)

        return SeedList([self.seed])


================================================
FILE: python/gym_ignition/context/__init__.py
================================================
# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

from . import gazebo


================================================
FILE: python/gym_ignition/context/gazebo/__init__.py
================================================
# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

from . import controllers, plugin


================================================
FILE: python/gym_ignition/context/gazebo/controllers.py
================================================
# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

from dataclasses import dataclass, field
from typing import Iterable, List, Tuple

from gym_ignition.context.gazebo import plugin

GRAVITY = (0, 0, -9.80665)


@dataclass
class ComputedTorqueFixedBase(plugin.GazeboPlugin):

    urdf: str
    kp: List[float]
    ki: List[float]
    kd: List[float]
    joints: List[str]
    gravity: Tuple[float, float, float] = field(default_factory=lambda: GRAVITY)

    # Private fields
    _name: str = field(init=False, repr=False, default="ComputedTorqueFixedBase")
    _plugin_name: str = field(init=False, repr=False, default="ControllerRunner")
    _plugin_class: str = field(
        init=False, repr=False, default="scenario::plugins::gazebo::ControllerRunner"
    )

    def to_xml(self) -> str:
        xml = f"""
        <controller name="{self._name}">
            <kp>{self._to_str(self.kp)}</kp>
            <ki>{self._to_str(self.ki)}</ki>
            <kd>{self._to_str(self.kd)}</kd>
            <urdf>{self.urdf}</urdf>
            <joints>{self._to_str(self.joints)}</joints>
            <gravity>{self._to_str(self.gravity)}</gravity>
        </controller>
        """

        return xml

    @staticmethod
    def _to_str(iterable: Iterable) -> str:

        return " ".join([str(el) for el in iterable])


================================================
FILE: python/gym_ignition/context/gazebo/plugin.py
================================================
# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

import abc
from dataclasses import dataclass, field
from typing import Tuple

# Default SDF version used in the serialized XML context
SDF_VERSION = 1.7

# Read the following for more information about dataclasses internals:
# https://florimond.dev/blog/articles/2018/10/reconciling-dataclasses-and-properties-in-python/


@dataclass
class GazeboPlugin(abc.ABC):
    """
    Base class of all World and Model plugins for Ignition Gazebo.

    The Plugin abstract class provides boilerplate code that simplifies and streamlines
    the definition of helper classes that insert Ignition Gazebo plugins to either World
    or Model objects.

    Classes that inherit from Plugin have to provide the following information:

    1) All the properties of the plugin as dataclass fields
    2) The private specification of the plugin (plugin name and plugin class)
    3) Optionally: the serialized XML context

    Example:

    .. code-block:: python

        plugin = MyPlugin(my_property=42)
        model = MyModel(world=my_world)

        model.insert_model_plugin(*plugin.args())
    """

    _plugin_name: str = field(init=False, repr=False)
    _plugin_class: str = field(init=False, repr=False)

    def to_xml(self) -> str:
        """
        Get the XML plugin content.

        Returns:
            The XML plugin content.
        """
        return ""

    def args(self) -> Tuple[str, str, str]:
        """
        Get the arguments passed to the ScenarI/O methods used to insert plugins.

        Returns:
            A tuple with the args required to insert the plugin.
        """
        return (
            str(self._plugin_name),
            str(self._plugin_class),
            GazeboPlugin.wrap_in_sdf(self.to_xml()),
        )

    @staticmethod
    def wrap_in_sdf(context: str) -> str:
        """
        Wrap the XML context inside a SDF root.

        Args:
            context: The XML string with the plugin's context.

        Returns:
            The plugin's context wrapped inside a SDF root.
        """

        return f"""<sdf version='{SDF_VERSION}'>{context}</sdf>"""


================================================
FILE: python/gym_ignition/randomizers/__init__.py
================================================
# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

from . import abc, gazebo_env_randomizer, model, physics


================================================
FILE: python/gym_ignition/randomizers/abc.py
================================================
# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

import abc

import gym_ignition.base.task

from scenario import core as scenario_core


class TaskRandomizer(abc.ABC):
    @abc.abstractmethod
    def randomize_task(self, task: gym_ignition.base.task.Task, **kwargs) -> None:
        """
        Randomize a :py:class:`~gym_ignition.base.task.Task` instance.

        Args:
            task: the task to randomize.

        Note:
            Note that each task has a :py:attr:`~gym_ignition.base.task.Task.world`
            property that provides access to the simulated
            :py:class:`scenario.bindings.core.World`.
        """
        pass


class PhysicsRandomizer(abc.ABC):
    """
    Abstract class that provides the machinery for randomizing the physics of a Task.

    Args:
        randomize_after_rollouts_num: defines after many rollouts physics should be
            randomized (i.e. the amount of times :py:meth:`gym.Env.reset` is called).
    """

    def __init__(self, randomize_after_rollouts_num: int = 0):

        self._rollout_counter = randomize_after_rollouts_num
        self.randomize_after_rollouts_num = randomize_after_rollouts_num

    @abc.abstractmethod
    def randomize_physics(self, task: gym_ignition.base.task.Task, **kwargs) -> None:
        """
        Method that insert and configures the physics of a Task's world.

        By default this method loads a plugin that uses DART with no randomizations.
        Randomizing physics engine parameters or changing physics engine backend could be
        done by redefining this method and passing it to
        :py:class:`~gym_ignition.runtimes.gazebo_runtime.GazeboRuntime`.

        Args:
            task: A task containing a world object without physics.
        """
        pass

    @abc.abstractmethod
    def get_engine(self):
        """
        Return the physics engine to use for the rollout.

        Note:

            Supported physics engines:

            - :py:const:`scenario.bindings.gazebo.PhysicsEngine_dart`

        Return:
            The desired physics engine to set in the world.
        """

        pass

    def increase_rollout_counter(self) -> None:
        """
        Increase the rollouts counter.
        """

        if self.randomize_after_rollouts_num != 0:
            assert self._rollout_counter != 0
            self._rollout_counter -= 1

    def physics_expired(self) -> bool:
        """
        Checks if the physics needs to be randomized.

        Return:
            True if the physics has expired, false otherwise.
        """

        if self.randomize_after_rollouts_num == 0:
            return False

        if self._rollout_counter == 0:
            self._rollout_counter = self.randomize_after_rollouts_num
            return True

        return False


class ModelRandomizer(abc.ABC):
    @abc.abstractmethod
    def randomize_model(
        self, task: gym_ignition.base.task.Task, **kwargs
    ) -> scenario_core.Model:
        """
        Randomize the model.

        Args:
            task: The task that operates on the model to randomize.

        Return:
            The randomized model.
        """
        pass


class ModelDescriptionRandomizer(abc.ABC):
    @abc.abstractmethod
    def randomize_model_description(
        self, task: gym_ignition.base.task.Task, **kwargs
    ) -> str:
        """
        Randomize the model description.

        Args:
            task: The task that operates on the model description to randomize.

        Return:
            A string with the randomized model description.
        """
        pass


================================================
FILE: python/gym_ignition/randomizers/gazebo_env_randomizer.py
================================================
# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

import abc
from typing import Callable, Dict, Optional, Union, cast

import gym
from gym_ignition.randomizers.abc import PhysicsRandomizer, TaskRandomizer
from gym_ignition.randomizers.physics import dart
from gym_ignition.runtimes import gazebo_runtime
from gym_ignition.utils import typing

MakeEnvCallable = Callable[[Optional[Dict]], gym.Env]


class GazeboEnvRandomizer(gym.Wrapper, TaskRandomizer, abc.ABC):
    """
    Base class to implement an environment randomizer for Ignition Gazebo.

    The randomizer is a :py:class:`gym.Wrapper` that extends the
    :py:meth:`gym.Env.reset` method. Objects that inherit from this class are used to
    setup the environment for the handled :py:class:`~gym_ignition.base.task.Task`.

    In its simplest form, a randomizer populates the world with all the models that need
    to be part of the simulation. The task could then operate on them from a
    :py:class:`~scenario.core.Model` object.

    More complex environments may require to randomize one or more simulated entities.
    Concrete classes that implement a randomizer could use
    :py:class:`~gym_ignition.randomizers.model.sdf.SDFRandomizer` to randomize the model
    and :py:class:`~gym_ignition.randomizers.abc.PhysicsRandomizer` to randomize
    the physics.

    Args:
        env: Defines the environment to handle. This argument could be either the string
            id if the environment does not need to be registered or a function that
            returns an environment object.
        physics_randomizer: Object that randomizes physics. The default physics engine is
            DART with no randomizations.

    Note:
        In order to randomize physics, the handled
        :py:class:`scenario.gazebo.GazeboSimulator` is destroyed and created again.
        This operation is demanding, consider randomizing physics at a low rate.
    """

    def __init__(
        self,
        env: Union[str, MakeEnvCallable],
        physics_randomizer: PhysicsRandomizer = dart.DART(),
        **kwargs,
    ):

        # Print the extra kwargs
        gym.logger.debug(f"GazeboEnvRandomizer: {dict(kwargs=kwargs)}")

        # Store the options
        self._env_option = env
        self._kwargs = dict(**kwargs, physics_engine=physics_randomizer.get_engine())

        # Create the environment
        env_to_wrap = self._create_environment(env=self._env_option, **self._kwargs)

        # Initialize the wrapper
        gym.Wrapper.__init__(self, env=env_to_wrap)

        # Store the physics randomizer
        self._physics_randomizer = physics_randomizer

    # ===============
    # gym.Env methods
    # ===============

    def reset(self, **kwargs) -> typing.Observation:

        # Reset the physics
        if self._physics_randomizer.physics_expired():

            # Get the random components of the task
            seed = self.env.task.seed
            np_random = self.env.task.np_random

            # Reset the runtime + task, creating a new Gazebo instance
            self.env.close()
            del self.env
            self.env = self._create_environment(self._env_option, **self._kwargs)

            # Restore the random components
            self.env.seed(seed=seed)
            assert self.env.task.seed == seed
            self.env.task.np_random = np_random

        # Mark the beginning of a new rollout
        self._physics_randomizer.increase_rollout_counter()

        # Reset the task through the TaskRandomizer
        self.randomize_task(task=self.env.task, gazebo=self.env.gazebo, **kwargs)

        ok_paused_run = self.env.gazebo.run(paused=True)

        if not ok_paused_run:
            raise RuntimeError("Failed to execute a paused Gazebo run")

        # Reset the Task
        return self.env.reset()

    # ===============
    # Private methods
    # ===============

    def _create_environment(
        self, env: Union[str, MakeEnvCallable], **kwargs
    ) -> gazebo_runtime.GazeboRuntime:

        if isinstance(env, str):
            env_to_wrap = self._create_from_id(env_id=env, **kwargs)

        elif callable(env):
            env_to_wrap = self._create_from_callable(make_env=env, **kwargs)

        else:
            raise ValueError("The type of env object was not recognized")

        if not isinstance(env_to_wrap.unwrapped, gazebo_runtime.GazeboRuntime):
            raise ValueError("The environment to wrap is not a GazeboRuntime")

        return cast(gazebo_runtime.GazeboRuntime, env_to_wrap)

    @staticmethod
    def _create_from_callable(make_env: MakeEnvCallable, **kwargs) -> gym.Env:

        env = make_env(**kwargs)
        return env

    @staticmethod
    def _create_from_id(env_id: str, **kwargs) -> gym.Env:

        env = gym.make(env_id, **kwargs)
        return env


================================================
FILE: python/gym_ignition/randomizers/model/__init__.py
================================================
# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

from . import sdf


================================================
FILE: python/gym_ignition/randomizers/model/sdf.py
================================================
# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

from enum import Enum, auto
from pathlib import Path
from typing import Dict, List, NamedTuple, Union

import numpy as np
from lxml import etree


class Distribution(Enum):
    Uniform = auto()
    Gaussian = auto()


class Method(Enum):
    Absolute = auto()
    Additive = auto()
    Coefficient = auto()


class RandomizationData(NamedTuple):
    xpath: str
    distribution: str
    parameters: "DistributionParameters"
    method: Method
    ignore_zeros: bool = False
    force_positive: bool = False
    element: etree.Element = None


class GaussianParams(NamedTuple):
    variance: float
    mean: float = None


class UniformParams(NamedTuple):
    low: float
    high: float


DistributionParameters = Union[UniformParams, GaussianParams]


class RandomizationDataBuilder:
    """
    Builder class of a :py:class:`~gym_ignition.randomizers.model.sdf.RandomizationData`
    object.

    Args:
        randomizer: The :py:class:`~gym_ignition.randomizers.model.sdf.SDFRandomizer`
            object to which the created randomization will be inserted.
    """

    def __init__(self, randomizer: "SDFRandomizer"):

        self.storage: Dict = {}
        self.randomizer = randomizer

    def at_xpath(self, xpath: str) -> "RandomizationDataBuilder":
        """
        Set the XPath pattern associated to the randomization.

        Args:
            xpath: The XPath pattern.

        Returns:
            The randomization builder to allow chaining methods.
        """
        self.storage["xpath"] = xpath
        return self

    def sampled_from(
        self, distribution: Distribution, parameters: DistributionParameters
    ) -> "RandomizationDataBuilder":
        """
        Set the distribution associated to the randomization.

        Args:
            distribution: The desired distribution.
            parameters: The namedtuple with the parameters of the distribution.

        Returns:
            The randomization builder to allow chaining methods.
        """

        self.storage["distribution"] = distribution
        self.storage["parameters"] = parameters

        if self.storage["distribution"] is Distribution.Gaussian and not isinstance(
            parameters, GaussianParams
        ):
            raise ValueError("Wrong parameters type")

        if self.storage["distribution"] is Distribution.Uniform and not isinstance(
            parameters, UniformParams
        ):
            raise ValueError("Wrong parameters type")

        return self

    def method(self, method: Method) -> "RandomizationDataBuilder":
        """
        Set the randomization method.

        Args:
            method: The desired randomization method.

        Returns:
            The randomization builder to allow chaining methods.
        """

        self.storage["method"] = method
        return self

    def ignore_zeros(self, ignore_zeros: bool) -> "RandomizationDataBuilder":
        """
        Ignore the randomization of values that are zero.

        If the value to randomize has a default value of 0 in the SDF, when this method
        is chained the randomization is skipped. In the case of a multi-match XPath
        pattern, the values that are not zero are not skipped.

        Args:
            ignore_zeros: True if zeros should be ignored, false otherwise.

        Returns:
            The randomization builder to allow chaining methods.
        """

        self.storage["ignore_zeros"] = ignore_zeros
        return self

    def force_positive(self, force_positive: bool = True) -> "RandomizationDataBuilder":
        """
        Force the randomized value to be greater than zero.

        This option is helpful to enforce that values e.g. the mass will stay positive
        regardless of the applied distribution parameters.

        Args:
            force_positive: True to force positive parameters, false otherwise.

        Returns:
            The randomization builder to allow chaining methods.
        """

        self.storage["force_positive"] = force_positive
        return self

    def add(self) -> None:
        """
        Close the chaining of methods and return to the SDF randomizer the configuration.

        Raises:
            RuntimeError: If the XPath pattern does not find any match in the SDF.
        """

        data = RandomizationData(**self.storage)

        if len(self.randomizer.find_xpath(data.xpath)) == 0:
            raise RuntimeError(f"Failed to find element matching XPath '{data.xpath}'")

        self.randomizer.insert(randomization_data=data)


class SDFRandomizer:
    """
    Randomized SDF files generator.

    Args:
        sdf_model: The absolute path to the SDF file.

    Raises:
       ValueError: If the SDF file does not exist.
    """

    def __init__(self, sdf_model: str):

        self._sdf_file = sdf_model

        if not Path(self._sdf_file).is_file():
            raise ValueError(f"File '{sdf_model}' does not exist")

        # Initialize the root
        tree = self._get_tree_from_file(self._sdf_file)
        self._root: etree.Element = tree.getroot()

        # List of randomizations
        self._randomizations: List[RandomizationData] = []

        # List of default values used with Method.Coefficient
        self._default_values: Dict[etree.Element, float] = {}

        # Store an independent RNG
        self.rng = np.random.default_rng()

    def seed(self, seed: int) -> None:
        """
        Seed the SDF randomizer.

        Args:
            seed: The seed number.
        """
        self.rng = np.random.default_rng(seed)

    def find_xpath(self, xpath: str) -> List[etree.Element]:
        """
        Find the elements that match an XPath pattern.

        This method could be helpful to test the matches of a XPath pattern before using
        it in :py:meth:`~gym_ignition.randomizers.model.sdf.RandomizationDataBuilder.at_xpath`.

        Args:
            xpath: The XPath pattern.

        Return:
            A list of elements matching the XPath pattern.
        """
        return self._root.findall(xpath)

    def process_data(self) -> None:
        """
        Process all the inserted randomizations.

        Raises:
            RuntimeError: If the XPath of a randomization has no matches.
        """

        # Since we support multi-match XPaths, we expand all the individual matches
        expanded_randomizations = []

        for data in self._randomizations:

            # Find all the matches
            elements: List[etree.Element] = self._root.findall(path=data.xpath)

            if len(elements) == 0:
                raise RuntimeError(f"Failed to find elements from XPath '{data.xpath}'")

            for element in elements:

                if data.ignore_zeros and float(self._get_element_text(element)) == 0:
                    continue

                # Get the precise XPath to the element
                element_xpath = element.getroottree().getpath(element)

                # Get the parameters
                params = data.parameters

                if data.method in {Method.Additive, Method.Coefficient}:
                    element_text = float(self._get_element_text(element))
                    self._default_values[element] = element_text

                # Update the data
                complete_data = data._replace(
                    xpath=element_xpath, element=element, parameters=params
                )

                expanded_randomizations.append(complete_data)

        # Store the updated data
        self._randomizations = expanded_randomizations

    def sample(self, pretty_print=False) -> str:
        """
        Sample a randomized SDF string.

        Args:
            pretty_print: True to pretty print the output.

        Raises:
            ValueError: If the distribution of a randomization is not recognized.
            ValueError: If the method of a randomization is not recognized.

        Returns:
            The randomized model as SDF string.
        """

        for data in self._randomizations:

            if data.distribution is Distribution.Gaussian:

                sample = self.rng.normal(
                    loc=data.parameters.mean, scale=data.parameters.variance
                )

            elif data.distribution is Distribution.Uniform:

                sample = self.rng.uniform(
                    low=data.parameters.low, high=data.parameters.high
                )

            else:
                raise ValueError("Distribution not recognized")

            # Update the value
            if data.method is Method.Absolute:

                data.element.text = str(sample)

            elif data.method is Method.Additive:

                default_value = self._default_values[data.element]
                data.element.text = str(sample + default_value)

            elif data.method is Method.Coefficient:

                default_value = self._default_values[data.element]
                data.element.text = str(sample * default_value)

            else:
                raise ValueError("Method not recognized")

            if data.force_positive:
                data.element.text = str(max(float(data.element.text), 0.0))

        return etree.tostring(self._root, pretty_print=pretty_print).decode()

    def new_randomization(self) -> RandomizationDataBuilder:
        """
        Start the chaining to build a new randomization.

        Return:
            A randomization builder.
        """
        return RandomizationDataBuilder(randomizer=self)

    def insert(self, randomization_data) -> None:
        """
        Insert a randomization.

        Args:
            randomization_data: A new randomization.
        """
        self._randomizations.append(randomization_data)

    def get_active_randomizations(self) -> List[RandomizationData]:
        """
        Return the active randomizations.

        This method could be helpful also in the case of multi-match XPath patterns to
        validate that the inserted randomizations have been processed correctly.

        Returns:
            The list of the active randomizations.
        """
        return self._randomizations

    def clean(self) -> None:
        """
        Clean the SDF randomizer.
        """

        self._randomizations = []
        self._default_values = {}

        tree = self._get_tree_from_file(self._sdf_file)
        self._root = tree.getroot()

    @staticmethod
    def _get_tree_from_file(xml_file) -> etree.ElementTree:

        parser = etree.XMLParser(remove_blank_text=True)
        tree = etree.parse(source=xml_file, parser=parser)

        return tree

    @staticmethod
    def _get_element_text(element: etree.Element) -> str:

        text = element.text

        if text is None:
            raise RuntimeError(f"The element {element.tag} does not have any content")

        return text


================================================
FILE: python/gym_ignition/randomizers/physics/__init__.py
================================================
# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

from . import dart


================================================
FILE: python/gym_ignition/randomizers/physics/dart.py
================================================
# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

import gym_ignition.base.task
from gym_ignition import randomizers

from scenario import gazebo as scenario


class DART(randomizers.abc.PhysicsRandomizer):
    """
    Class that configures the Gazebo World of a Task to use the DART physics engine.

    Note:
        This class does not apply any physics randomization.
    """

    def __init__(self):

        super().__init__()

    def get_engine(self):

        return scenario.PhysicsEngine_dart

    def randomize_physics(self, task: gym_ignition.base.task.Task, **kwargs) -> None:

        pass


================================================
FILE: python/gym_ignition/rbd/__init__.py
================================================
# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

from . import conversions, idyntree, utils


================================================
FILE: python/gym_ignition/rbd/conversions.py
================================================
import abc
from typing import Tuple

import numpy as np
from scipy.spatial.transform import Rotation


class Transform(abc.ABC):
    @staticmethod
    def from_position_and_quaternion(
        position: np.ndarray, quaternion: np.ndarray
    ) -> np.ndarray:

        if quaternion.size != 4:
            raise ValueError("Quaternion array must have 4 elements")

        rotation = Quaternion.to_rotation(quaternion)
        transform = Transform.from_position_and_rotation(
            position=position, rotation=rotation
        )

        return transform

    @staticmethod
    def from_position_and_rotation(
        position: np.ndarray, rotation: np.ndarray
    ) -> np.ndarray:

        if position.size != 3:
            raise ValueError("Position array must have 3 elements")

        if rotation.shape != (3, 3):
            raise ValueError("Rotation must be a square 3x3 matrix")

        transform = np.eye(4)
        transform[0:3, 3] = position
        transform[0:3, 0:3] = rotation

        return transform

    @staticmethod
    def to_position_and_rotation(
        transform: np.ndarray,
    ) -> Tuple[np.ndarray, np.ndarray]:

        if transform.shape != (4, 4):
            raise ValueError("Transform must be a 4x4 matrix")

        position = transform[0:3, 3]
        rotation = transform[0:3, 0:3]

        return position, rotation

    @staticmethod
    def to_position_and_quaternion(
        transform: np.ndarray,
    ) -> Tuple[np.ndarray, np.ndarray]:

        p, R = Transform.to_position_and_rotation(transform=transform)
        return p, Quaternion.from_matrix(matrix=R)


class Quaternion(abc.ABC):
    @staticmethod
    def to_wxyz(xyzw: np.ndarray) -> np.ndarray:

        if xyzw.shape != (4,):
            raise ValueError(xyzw)

        return xyzw[[3, 0, 1, 2]]

    @staticmethod
    def to_xyzw(wxyz: np.ndarray) -> np.ndarray:

        if wxyz.shape != (4,):
            raise ValueError(wxyz)

        return wxyz[[1, 2, 3, 0]]

    @staticmethod
    def to_rotation(quaternion: np.ndarray) -> np.ndarray:

        if quaternion.shape != (4,):
            raise ValueError(quaternion)

        xyzw = Quaternion.to_xyzw(quaternion)

        return Rotation.from_quat(xyzw).as_matrix()

    @staticmethod
    def from_matrix(matrix: np.ndarray) -> np.ndarray:

        if matrix.shape != (3, 3):
            raise ValueError(matrix)

        quaternion_xyzw = Rotation.from_matrix(matrix).as_quat()
        quaternion_wxyz = Quaternion.to_wxyz(quaternion_xyzw)

        return quaternion_wxyz


================================================
FILE: python/gym_ignition/rbd/idyntree/__init__.py
================================================
# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

from . import helpers, inverse_kinematics_nlp, kindyncomputations, numpy


================================================
FILE: python/gym_ignition/rbd/idyntree/helpers.py
================================================
# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

import abc
import os
from enum import Enum, auto
from typing import List

import idyntree.bindings as idt
from gym_ignition.utils import resource_finder


class FrameVelocityRepresentation(Enum):

    MIXED_REPRESENTATION = auto()
    BODY_FIXED_REPRESENTATION = auto()
    INERTIAL_FIXED_REPRESENTATION = auto()

    def to_idyntree(self):

        if self.value == FrameVelocityRepresentation.MIXED_REPRESENTATION.value:
            return idt.MIXED_REPRESENTATION
        elif self.value == FrameVelocityRepresentation.BODY_FIXED_REPRESENTATION.value:
            return idt.BODY_FIXED_REPRESENTATION
        elif (
            self.value
            == FrameVelocityRepresentation.INERTIAL_FIXED_REPRESENTATION.value
        ):
            return idt.INERTIAL_FIXED_REPRESENTATION
        else:
            raise ValueError(self.value)


class iDynTreeHelpers(abc.ABC):
    @staticmethod
    def get_model_loader(model_file: str, considered_joints: List[str] = None):

        # Find the urdf file
        urdf_file = resource_finder.find_resource(file_name=model_file)

        # Get the file extension
        folder, model_file = os.path.split(urdf_file)
        model_name, extension = os.path.splitext(model_file)

        if extension == ".sdf":
            raise RuntimeError("SDF models are not currently supported by iDynTree")

        # Create the model loader
        mdl_loader = idt.ModelLoader()

        # Load the urdf model
        if considered_joints is None:
            ok_load = mdl_loader.loadModelFromFile(urdf_file)
        else:
            ok_load = mdl_loader.loadReducedModelFromFile(urdf_file, considered_joints)

        if not ok_load:
            raise RuntimeError(f"Failed to load model from file '{urdf_file}'")

        return mdl_loader

    @staticmethod
    def get_kindyncomputations(
        model_file: str,
        considered_joints: List[str] = None,
        velocity_representation: FrameVelocityRepresentation = FrameVelocityRepresentation.MIXED_REPRESENTATION,
    ):

        # Get the model loader
        model_loader = iDynTreeHelpers.get_model_loader(model_file, considered_joints)

        # Create KinDynComputations and insert the model
        kindyn = idt.KinDynComputations()
        ok_load = kindyn.loadRobotModel(model_loader.model())

        if not ok_load:
            raise RuntimeError("Failed to load model")

        # Configure the velocity representation
        velocity_representation_idyntree = velocity_representation.to_idyntree()
        ok_repr = kindyn.setFrameVelocityRepresentation(
            velocity_representation_idyntree
        )

        if not ok_repr:
            raise RuntimeError("Failed to set the velocity representation")

        return kindyn


================================================
FILE: python/gym_ignition/rbd/idyntree/inverse_kinematics_nlp.py
================================================
# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.
# This software may be modified and distributed under the terms of the
# GNU Lesser General Public License v2.1 or any later version.

import os
from dataclasses import dataclass
from enum import Enum, auto
from typing import Dict, List, Optional, Tuple, Union

import idyntree.bindings as idt
import numpy as np
from gym_ignition import rbd


class TargetType(Enum):

    POSITION = auto()
    ROTATION = auto()
    POSE = auto()


@dataclass
class TransformTargetData:

    position: np.ndarray
    quaternion: np.ndarray


@dataclass
class TargetData:

    type: TargetType
    weight: Union[float, Tuple[float, float]]
   
Download .txt
gitextract_2yu_wlwv/

├── .clang-format
├── .docker/
│   ├── Dockerfile
│   ├── base.Dockerfile
│   ├── cicd-devel.Dockerfile
│   ├── cicd-master.Dockerfile
│   ├── docker-compose.yml
│   ├── entrypoint.sh
│   └── setup_virtualenv.sh
├── .github/
│   ├── CODEOWNERS
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── release.yml
│   └── workflows/
│       ├── cicd.yml
│       ├── docker.yml
│       └── style.yml
├── .gitignore
├── CMakeLists.txt
├── LICENSE
├── README.md
├── docs/
│   ├── CMakeLists.txt
│   ├── doxygen/
│   │   └── CMakeLists.txt
│   └── sphinx/
│       ├── CMakeLists.txt
│       ├── _templates/
│       │   ├── module.rst_t
│       │   ├── package.rst_t
│       │   ├── toc.rst_t
│       │   ├── versioning.html
│       │   └── versions.html
│       ├── apidoc/
│       │   ├── gym-ignition/
│       │   │   ├── gym_ignition.base.rst
│       │   │   ├── gym_ignition.context.gazebo.rst
│       │   │   ├── gym_ignition.context.rst
│       │   │   ├── gym_ignition.randomizers.model.rst
│       │   │   ├── gym_ignition.randomizers.physics.rst
│       │   │   ├── gym_ignition.randomizers.rst
│       │   │   ├── gym_ignition.rbd.idyntree.rst
│       │   │   ├── gym_ignition.rbd.rst
│       │   │   ├── gym_ignition.rst
│       │   │   ├── gym_ignition.runtimes.rst
│       │   │   ├── gym_ignition.scenario.rst
│       │   │   └── gym_ignition.utils.rst
│       │   ├── gym-ignition-environments/
│       │   │   ├── gym_ignition_environments.models.rst
│       │   │   ├── gym_ignition_environments.randomizers.rst
│       │   │   ├── gym_ignition_environments.rst
│       │   │   └── gym_ignition_environments.tasks.rst
│       │   └── scenario/
│       │       ├── scenario.bindings.rst
│       │       └── scenario.rst
│       ├── breathe/
│       │   ├── core.rst
│       │   └── gazebo.rst
│       ├── conf.py
│       ├── getting_started/
│       │   ├── gym-ignition.rst
│       │   ├── manipulation.rst
│       │   └── scenario.rst
│       ├── index.html
│       ├── index.rst
│       ├── info/
│       │   ├── faq.rst
│       │   └── limitations.rst
│       ├── installation/
│       │   ├── developer.rst
│       │   ├── nightly.rst
│       │   ├── stable.rst
│       │   ├── support_policy.rst
│       │   ├── system_configuration.rst
│       │   └── virtual_environment.rst
│       ├── what/
│       │   ├── what_is_gym_ignition.rst
│       │   └── what_is_scenario.rst
│       └── why/
│           ├── motivations.rst
│           ├── why_gym_ignition.rst
│           ├── why_ignition_gazebo.rst
│           └── why_scenario.rst
├── examples/
│   ├── panda_pick_and_place.py
│   └── python/
│       └── launch_cartpole.py
├── pyproject.toml
├── python/
│   ├── gym_ignition/
│   │   ├── __init__.py
│   │   ├── base/
│   │   │   ├── __init__.py
│   │   │   ├── runtime.py
│   │   │   └── task.py
│   │   ├── context/
│   │   │   ├── __init__.py
│   │   │   └── gazebo/
│   │   │       ├── __init__.py
│   │   │       ├── controllers.py
│   │   │       └── plugin.py
│   │   ├── randomizers/
│   │   │   ├── __init__.py
│   │   │   ├── abc.py
│   │   │   ├── gazebo_env_randomizer.py
│   │   │   ├── model/
│   │   │   │   ├── __init__.py
│   │   │   │   └── sdf.py
│   │   │   └── physics/
│   │   │       ├── __init__.py
│   │   │       └── dart.py
│   │   ├── rbd/
│   │   │   ├── __init__.py
│   │   │   ├── conversions.py
│   │   │   ├── idyntree/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── helpers.py
│   │   │   │   ├── inverse_kinematics_nlp.py
│   │   │   │   ├── kindyncomputations.py
│   │   │   │   └── numpy.py
│   │   │   └── utils.py
│   │   ├── runtimes/
│   │   │   ├── __init__.py
│   │   │   ├── gazebo_runtime.py
│   │   │   └── realtime_runtime.py
│   │   ├── scenario/
│   │   │   ├── __init__.py
│   │   │   ├── model_with_file.py
│   │   │   └── model_wrapper.py
│   │   └── utils/
│   │       ├── __init__.py
│   │       ├── logger.py
│   │       ├── math.py
│   │       ├── misc.py
│   │       ├── resource_finder.py
│   │       ├── scenario.py
│   │       └── typing.py
│   └── gym_ignition_environments/
│       ├── __init__.py
│       ├── models/
│       │   ├── __init__.py
│       │   ├── cartpole.py
│       │   ├── icub.py
│       │   ├── panda.py
│       │   └── pendulum.py
│       ├── randomizers/
│       │   ├── __init__.py
│       │   ├── cartpole.py
│       │   └── cartpole_no_rand.py
│       └── tasks/
│           ├── __init__.py
│           ├── cartpole_continuous_balancing.py
│           ├── cartpole_continuous_swingup.py
│           ├── cartpole_discrete_balancing.py
│           └── pendulum_swingup.py
├── scenario/
│   ├── CMakeLists.txt
│   ├── README.md
│   ├── bindings/
│   │   ├── CMakeLists.txt
│   │   ├── __init__.py
│   │   ├── core/
│   │   │   ├── CMakeLists.txt
│   │   │   └── core.i
│   │   └── gazebo/
│   │       ├── CMakeLists.txt
│   │       ├── gazebo.i
│   │       └── to_gazebo.i
│   ├── cmake/
│   │   ├── AddUninstallTarget.cmake
│   │   ├── AliasImportedTarget.cmake
│   │   ├── FindIgnitionDistribution.cmake
│   │   ├── FindPackageHandleStandardArgs.cmake
│   │   ├── FindPackageMessage.cmake
│   │   ├── FindPython/
│   │   │   └── Support.cmake
│   │   ├── FindPython3.cmake
│   │   ├── FindSphinx.cmake
│   │   ├── FindSphinxApidoc.cmake
│   │   ├── FindSphinxMultiVersion.cmake
│   │   ├── ImportTargetsCitadel.cmake
│   │   ├── ImportTargetsDome.cmake
│   │   ├── ImportTargetsEdifice.cmake
│   │   └── ImportTargetsFortress.cmake
│   ├── deps/
│   │   ├── CMakeLists.txt
│   │   └── clara/
│   │       └── clara.hpp
│   ├── pyproject.toml
│   ├── setup.cfg
│   ├── setup.py
│   └── src/
│       ├── CMakeLists.txt
│       ├── controllers/
│       │   ├── CMakeLists.txt
│       │   ├── include/
│       │   │   └── scenario/
│       │   │       └── controllers/
│       │   │           ├── ComputedTorqueFixedBase.h
│       │   │           ├── Controller.h
│       │   │           └── References.h
│       │   └── src/
│       │       └── ComputedTorqueFixedBase.cpp
│       ├── core/
│       │   ├── CMakeLists.txt
│       │   ├── include/
│       │   │   └── scenario/
│       │   │       └── core/
│       │   │           ├── Joint.h
│       │   │           ├── Link.h
│       │   │           ├── Model.h
│       │   │           ├── World.h
│       │   │           └── utils/
│       │   │               ├── Log.h
│       │   │               ├── signals.h
│       │   │               └── utils.h
│       │   └── src/
│       │       ├── signals.cpp
│       │       └── utils.cpp
│       ├── gazebo/
│       │   ├── CMakeLists.txt
│       │   ├── include/
│       │   │   └── scenario/
│       │   │       └── gazebo/
│       │   │           ├── GazeboEntity.h
│       │   │           ├── GazeboSimulator.h
│       │   │           ├── Joint.h
│       │   │           ├── Link.h
│       │   │           ├── Log.h
│       │   │           ├── Model.h
│       │   │           ├── World.h
│       │   │           ├── components/
│       │   │           │   ├── BasePoseTarget.h
│       │   │           │   ├── BaseWorldAccelerationTarget.h
│       │   │           │   ├── BaseWorldVelocityTarget.h
│       │   │           │   ├── ExternalWorldWrenchCmdWithDuration.h
│       │   │           │   ├── HistoryOfAppliedJointForces.h
│       │   │           │   ├── JointAcceleration.h
│       │   │           │   ├── JointAccelerationTarget.h
│       │   │           │   ├── JointControlMode.h
│       │   │           │   ├── JointController.h
│       │   │           │   ├── JointControllerPeriod.h
│       │   │           │   ├── JointPID.h
│       │   │           │   ├── JointPositionTarget.h
│       │   │           │   ├── JointVelocityTarget.h
│       │   │           │   ├── SimulatedTime.h
│       │   │           │   └── Timestamp.h
│       │   │           ├── exceptions.h
│       │   │           ├── helpers.h
│       │   │           └── utils.h
│       │   └── src/
│       │       ├── GazeboSimulator.cpp
│       │       ├── Joint.cpp
│       │       ├── Link.cpp
│       │       ├── Model.cpp
│       │       ├── World.cpp
│       │       ├── helpers.cpp
│       │       └── utils.cpp
│       └── plugins/
│           ├── CMakeLists.txt
│           ├── ControllerRunner/
│           │   ├── CMakeLists.txt
│           │   ├── ControllerRunner.cpp
│           │   ├── ControllerRunner.h
│           │   ├── ControllersFactory.cpp
│           │   └── ControllersFactory.h
│           ├── JointController/
│           │   ├── CMakeLists.txt
│           │   ├── JointController.cpp
│           │   └── JointController.h
│           └── Physics/
│               ├── CMakeLists.txt
│               ├── CanonicalLinkModelTracker.hh
│               ├── EntityFeatureMap.hh
│               ├── Physics.cc
│               └── Physics.hh
├── setup.cfg
├── setup.py
└── tests/
    ├── .python/
    │   ├── __init__.py
    │   ├── test_contacts.py
    │   ├── test_environments_gazebowrapper.py
    │   ├── test_externalforce.py
    │   ├── test_joint_force.py
    │   ├── test_pendulum_wrt_ground_truth.py
    │   ├── test_rates.py
    │   ├── test_robot_base.py
    │   ├── test_robot_controller.py
    │   ├── test_runtimes.py
    │   └── utils.py
    ├── __init__.py
    ├── assets/
    │   └── worlds/
    │       └── fuel_support.sdf
    ├── common/
    │   ├── __init__.py
    │   └── utils.py
    ├── test_gym_ignition/
    │   ├── __init__.py
    │   ├── test_inverse_kinematics.py
    │   ├── test_normalization.py
    │   ├── test_reproducibility.py
    │   └── test_sdf_randomizer.py
    └── test_scenario/
        ├── __init__.py
        ├── test_contacts.py
        ├── test_custom_controllers.py
        ├── test_external_wrench.py
        ├── test_gazebo_simulator.py
        ├── test_ignition_fuel.py
        ├── test_link_velocities.py
        ├── test_model.py
        ├── test_multi_world.py
        ├── test_pid_controllers.py
        ├── test_velocity_direct.py
        └── test_world.py
Download .txt
SYMBOL INDEX (679 symbols across 115 files)

FILE: examples/panda_pick_and_place.py
  function add_panda_controller (line 24) | def add_panda_controller(
  function get_panda_ik (line 56) | def get_panda_ik(
  function insert_bucket (line 94) | def insert_bucket(world: scenario_gazebo.World) -> scenario_gazebo.Model:
  function insert_table (line 120) | def insert_table(world: scenario_gazebo.World) -> scenario_gazebo.Model:
  function insert_cube_in_operating_area (line 140) | def insert_cube_in_operating_area(
  function solve_ik (line 169) | def solve_ik(
  function end_effector_reached (line 189) | def end_effector_reached(
  function get_unload_position (line 206) | def get_unload_position(bucket: scenario_core.Model) -> np.ndarray:
  class FingersAction (line 211) | class FingersAction(enum.Enum):
  function move_fingers (line 217) | def move_fingers(

FILE: examples/python/launch_cartpole.py
  function make_env_from_id (line 22) | def make_env_from_id(env_id: str, **kwargs) -> gym.Env:

FILE: python/gym_ignition/__init__.py
  function initialize_verbosity (line 20) | def initialize_verbosity() -> None:

FILE: python/gym_ignition/base/runtime.py
  class Runtime (line 11) | class Runtime(gym.Env, abc.ABC):
    method __init__ (line 63) | def __init__(self, task: Task, agent_rate: float):
    method timestamp (line 72) | def timestamp(self) -> float:

FILE: python/gym_ignition/base/task.py
  class Task (line 23) | class Task(abc.ABC):
    method __init__ (line 55) | def __init__(self, agent_rate: float) -> None:
    method world (line 79) | def world(self) -> core.World:
    method world (line 93) | def world(self, world: core.World) -> None:
    method has_world (line 101) | def has_world(self) -> bool:
    method create_spaces (line 116) | def create_spaces(self) -> Tuple[ActionSpace, ObservationSpace]:
    method reset_task (line 136) | def reset_task(self) -> None:
    method set_action (line 149) | def set_action(self, action: Action) -> None:
    method get_observation (line 164) | def get_observation(self) -> Observation:
    method get_reward (line 180) | def get_reward(self) -> Reward:
    method is_done (line 195) | def is_done(self) -> bool:
    method get_info (line 212) | def get_info(self) -> Dict:
    method seed_task (line 221) | def seed_task(self, seed: int = None) -> SeedList:

FILE: python/gym_ignition/context/gazebo/controllers.py
  class ComputedTorqueFixedBase (line 14) | class ComputedTorqueFixedBase(plugin.GazeboPlugin):
    method to_xml (line 30) | def to_xml(self) -> str:
    method _to_str (line 45) | def _to_str(iterable: Iterable) -> str:

FILE: python/gym_ignition/context/gazebo/plugin.py
  class GazeboPlugin (line 17) | class GazeboPlugin(abc.ABC):
    method to_xml (line 44) | def to_xml(self) -> str:
    method args (line 53) | def args(self) -> Tuple[str, str, str]:
    method wrap_in_sdf (line 67) | def wrap_in_sdf(context: str) -> str:

FILE: python/gym_ignition/randomizers/abc.py
  class TaskRandomizer (line 12) | class TaskRandomizer(abc.ABC):
    method randomize_task (line 14) | def randomize_task(self, task: gym_ignition.base.task.Task, **kwargs) ...
  class PhysicsRandomizer (line 29) | class PhysicsRandomizer(abc.ABC):
    method __init__ (line 38) | def __init__(self, randomize_after_rollouts_num: int = 0):
    method randomize_physics (line 44) | def randomize_physics(self, task: gym_ignition.base.task.Task, **kwarg...
    method get_engine (line 59) | def get_engine(self):
    method increase_rollout_counter (line 75) | def increase_rollout_counter(self) -> None:
    method physics_expired (line 84) | def physics_expired(self) -> bool:
  class ModelRandomizer (line 102) | class ModelRandomizer(abc.ABC):
    method randomize_model (line 104) | def randomize_model(
  class ModelDescriptionRandomizer (line 119) | class ModelDescriptionRandomizer(abc.ABC):
    method randomize_model_description (line 121) | def randomize_model_description(

FILE: python/gym_ignition/randomizers/gazebo_env_randomizer.py
  class GazeboEnvRandomizer (line 17) | class GazeboEnvRandomizer(gym.Wrapper, TaskRandomizer, abc.ABC):
    method __init__ (line 48) | def __init__(
    method reset (line 75) | def reset(self, **kwargs) -> typing.Observation:
    method _create_environment (line 112) | def _create_environment(
    method _create_from_callable (line 131) | def _create_from_callable(make_env: MakeEnvCallable, **kwargs) -> gym....
    method _create_from_id (line 137) | def _create_from_id(env_id: str, **kwargs) -> gym.Env:

FILE: python/gym_ignition/randomizers/model/sdf.py
  class Distribution (line 13) | class Distribution(Enum):
  class Method (line 18) | class Method(Enum):
  class RandomizationData (line 24) | class RandomizationData(NamedTuple):
  class GaussianParams (line 34) | class GaussianParams(NamedTuple):
  class UniformParams (line 39) | class UniformParams(NamedTuple):
  class RandomizationDataBuilder (line 47) | class RandomizationDataBuilder:
    method __init__ (line 57) | def __init__(self, randomizer: "SDFRandomizer"):
    method at_xpath (line 62) | def at_xpath(self, xpath: str) -> "RandomizationDataBuilder":
    method sampled_from (line 75) | def sampled_from(
    method method (line 104) | def method(self, method: Method) -> "RandomizationDataBuilder":
    method ignore_zeros (line 118) | def ignore_zeros(self, ignore_zeros: bool) -> "RandomizationDataBuilder":
    method force_positive (line 136) | def force_positive(self, force_positive: bool = True) -> "Randomizatio...
    method add (line 153) | def add(self) -> None:
  class SDFRandomizer (line 169) | class SDFRandomizer:
    method __init__ (line 180) | def __init__(self, sdf_model: str):
    method seed (line 200) | def seed(self, seed: int) -> None:
    method find_xpath (line 209) | def find_xpath(self, xpath: str) -> List[etree.Element]:
    method process_data (line 224) | def process_data(self) -> None:
    method sample (line 268) | def sample(self, pretty_print=False) -> str:
    method new_randomization (line 323) | def new_randomization(self) -> RandomizationDataBuilder:
    method insert (line 332) | def insert(self, randomization_data) -> None:
    method get_active_randomizations (line 341) | def get_active_randomizations(self) -> List[RandomizationData]:
    method clean (line 353) | def clean(self) -> None:
    method _get_tree_from_file (line 365) | def _get_tree_from_file(xml_file) -> etree.ElementTree:
    method _get_element_text (line 373) | def _get_element_text(element: etree.Element) -> str:

FILE: python/gym_ignition/randomizers/physics/dart.py
  class DART (line 11) | class DART(randomizers.abc.PhysicsRandomizer):
    method __init__ (line 19) | def __init__(self):
    method get_engine (line 23) | def get_engine(self):
    method randomize_physics (line 27) | def randomize_physics(self, task: gym_ignition.base.task.Task, **kwarg...

FILE: python/gym_ignition/rbd/conversions.py
  class Transform (line 8) | class Transform(abc.ABC):
    method from_position_and_quaternion (line 10) | def from_position_and_quaternion(
    method from_position_and_rotation (line 25) | def from_position_and_rotation(
    method to_position_and_rotation (line 42) | def to_position_and_rotation(
    method to_position_and_quaternion (line 55) | def to_position_and_quaternion(
  class Quaternion (line 63) | class Quaternion(abc.ABC):
    method to_wxyz (line 65) | def to_wxyz(xyzw: np.ndarray) -> np.ndarray:
    method to_xyzw (line 73) | def to_xyzw(wxyz: np.ndarray) -> np.ndarray:
    method to_rotation (line 81) | def to_rotation(quaternion: np.ndarray) -> np.ndarray:
    method from_matrix (line 91) | def from_matrix(matrix: np.ndarray) -> np.ndarray:

FILE: python/gym_ignition/rbd/idyntree/helpers.py
  class FrameVelocityRepresentation (line 14) | class FrameVelocityRepresentation(Enum):
    method to_idyntree (line 20) | def to_idyntree(self):
  class iDynTreeHelpers (line 35) | class iDynTreeHelpers(abc.ABC):
    method get_model_loader (line 37) | def get_model_loader(model_file: str, considered_joints: List[str] = N...
    method get_kindyncomputations (line 64) | def get_kindyncomputations(

FILE: python/gym_ignition/rbd/idyntree/inverse_kinematics_nlp.py
  class TargetType (line 15) | class TargetType(Enum):
  class TransformTargetData (line 23) | class TransformTargetData:
  class TargetData (line 30) | class TargetData:
  class IKSolution (line 38) | class IKSolution:
  class RotationParametrization (line 45) | class RotationParametrization(Enum):
    method to_idyntree (line 50) | def to_idyntree(self):
  class TargetResolutionMode (line 62) | class TargetResolutionMode(Enum):
    method to_idyntree (line 69) | def to_idyntree(self):
  class InverseKinematicsNLP (line 87) | class InverseKinematicsNLP:
    method __init__ (line 88) | def __init__(
    method initialize (line 108) | def initialize(
    method set_current_robot_configuration (line 180) | def set_current_robot_configuration(
    method set_current_joint_configuration (line 209) | def set_current_joint_configuration(
    method add_target (line 227) | def add_target(
    method add_com_target (line 307) | def add_com_target(
    method update_position_target (line 327) | def update_position_target(self, target_name: str, position: np.ndarra...
    method update_rotation_target (line 350) | def update_rotation_target(self, target_name: str, quaternion: np.ndar...
    method update_transform_target (line 373) | def update_transform_target(
    method update_com_target (line 401) | def update_com_target(self, position: np.ndarray) -> None:
    method deactivate_com_target (line 419) | def deactivate_com_target(self) -> None:
    method add_frame_transform_constraint (line 430) | def add_frame_transform_constraint(
    method add_frame_position_constraint (line 443) | def add_frame_position_constraint(
    method add_frame_rotation_constraint (line 454) | def add_frame_rotation_constraint(
    method update_frame_transform_constraint (line 465) | def update_frame_transform_constraint(
    method deactivate_frame_constraint (line 480) | def deactivate_frame_constraint(self, frame_name: str) -> None:
    method solve (line 494) | def solve(self) -> None:
    method warm_start_from (line 502) | def warm_start_from(
    method get_base_frame (line 548) | def get_base_frame(self) -> str:
    method get_available_target_names (line 552) | def get_available_target_names(self) -> List[str]:
    method get_active_target_names (line 565) | def get_active_target_names(self, target_type: TargetType = None) -> L...
    method get_target_data (line 577) | def get_target_data(self, target_name: str) -> TargetData:
    method get_full_solution (line 581) | def get_full_solution(self) -> IKSolution:
    method get_reduced_solution (line 602) | def get_reduced_solution(self) -> IKSolution:
    method _get_model_loader (line 628) | def _get_model_loader(
    method _warm_start_with_last_solution (line 651) | def _warm_start_with_last_solution(self) -> None:

FILE: python/gym_ignition/rbd/idyntree/kindyncomputations.py
  class KinDynComputations (line 17) | class KinDynComputations:
    method __init__ (line 18) | def __init__(
    method joint_serialization (line 44) | def joint_serialization(self) -> List[str]:
    method set_robot_state (line 48) | def set_robot_state(
    method set_robot_state_from_model (line 98) | def set_robot_state_from_model(
    method get_floating_base (line 139) | def get_floating_base(self) -> str:
    method get_joint_positions (line 143) | def get_joint_positions(self) -> np.ndarray:
    method get_joint_velocities (line 152) | def get_joint_velocities(self) -> np.ndarray:
    method get_model_velocity (line 161) | def get_model_velocity(self) -> np.ndarray:
    method get_model_position (line 170) | def get_model_position(self) -> np.ndarray:
    method get_world_transform (line 179) | def get_world_transform(self, frame_name: str) -> np.ndarray:
    method get_relative_transform (line 188) | def get_relative_transform(
    method get_world_base_transform (line 204) | def get_world_base_transform(self) -> np.ndarray:
    method get_relative_transform_explicit (line 209) | def get_relative_transform_explicit(
    method get_relative_adjoint_wrench_transform_explicit (line 266) | def get_relative_adjoint_wrench_transform_explicit(
    method get_mass_matrix (line 289) | def get_mass_matrix(self) -> np.ndarray:
    method get_generalized_gravity_forces (line 298) | def get_generalized_gravity_forces(self) -> np.ndarray:
    method get_bias_forces (line 312) | def get_bias_forces(self) -> np.ndarray:
    method get_momentum (line 326) | def get_momentum(self) -> Tuple[np.ndarray, np.ndarray]:
    method get_centroidal_momentum (line 334) | def get_centroidal_momentum(self) -> Tuple[np.ndarray, np.ndarray]:
    method get_com_position (line 342) | def get_com_position(self) -> np.ndarray:
    method get_com_velocity (line 347) | def get_com_velocity(self) -> np.ndarray:
    method get_average_velocity (line 380) | def get_average_velocity(self) -> np.ndarray:
    method get_centroidal_average_velocity (line 385) | def get_centroidal_average_velocity(self) -> np.ndarray:
    method get_frame_jacobian (line 390) | def get_frame_jacobian(self, frame_name: str) -> np.ndarray:
    method get_linear_angular_momentum_jacobian (line 402) | def get_linear_angular_momentum_jacobian(self) -> np.ndarray:
    method get_centroidal_total_momentum_jacobian (line 411) | def get_centroidal_total_momentum_jacobian(self) -> np.ndarray:
    method get_average_velocity_jacobian (line 420) | def get_average_velocity_jacobian(self) -> np.ndarray:
    method get_centroidal_average_velocity_jacobian (line 429) | def get_centroidal_average_velocity_jacobian(self) -> np.ndarray:
    method get_frame_bias_acc (line 438) | def get_frame_bias_acc(self, frame_name: str) -> np.ndarray:
    method get_com_bias_acc (line 447) | def get_com_bias_acc(self) -> np.ndarray:

FILE: python/gym_ignition/rbd/idyntree/numpy.py
  class FromNumPy (line 9) | class FromNumPy(abc.ABC):
    method to_idyntree_dyn_vector (line 11) | def to_idyntree_dyn_vector(array: np.ndarray) -> idt.VectorDynSize:
    method to_idyntree_fixed_vector (line 16) | def to_idyntree_fixed_vector(array: np.ndarray):
    method to_idyntree_position (line 36) | def to_idyntree_position(position: np.ndarray) -> idt.Position:
    method to_idyntree_rotation (line 44) | def to_idyntree_rotation(quaternion: np.ndarray) -> idt.Rotation:
    method to_idyntree_transform (line 57) | def to_idyntree_transform(
    method to_idyntree_twist (line 80) | def to_idyntree_twist(
  class ToNumPy (line 97) | class ToNumPy(abc.ABC):
    method from_idyntree_vector (line 99) | def from_idyntree_vector(vector) -> np.ndarray:
    method from_idyntree_transform (line 118) | def from_idyntree_transform(

FILE: python/gym_ignition/rbd/utils.py
  function wedge (line 8) | def wedge(vector3: np.ndarray) -> np.ndarray:
  function vee (line 37) | def vee(matrix3x3: np.ndarray) -> np.ndarray:
  function extract_skew (line 59) | def extract_skew(matrix: np.ndarray) -> np.ndarray:
  function extract_symm (line 76) | def extract_symm(matrix: np.ndarray) -> np.ndarray:

FILE: python/gym_ignition/runtimes/gazebo_runtime.py
  class GazeboRuntime (line 16) | class GazeboRuntime(runtime.Runtime):
    method __init__ (line 38) | def __init__(
    method timestamp (line 95) | def timestamp(self) -> float:
    method step (line 103) | def step(self, action: Action) -> State:
    method reset (line 134) | def reset(self) -> Observation:
    method render (line 154) | def render(self, mode: str = "human", **kwargs) -> None:
    method close (line 166) | def close(self) -> None:
    method seed (line 173) | def seed(self, seed: int = None) -> SeedList:
    method gazebo (line 190) | def gazebo(self) -> scenario.GazeboSimulator:
    method world (line 221) | def world(self) -> scenario.World:

FILE: python/gym_ignition/runtimes/realtime_runtime.py
  class RealTimeRuntime (line 9) | class RealTimeRuntime(runtime.Runtime):
    method __init__ (line 18) | def __init__(self, task_cls: type, robot_cls: type, agent_rate: float,...
    method timestamp (line 35) | def timestamp(self) -> float:
    method step (line 43) | def step(self, action: Action) -> State:
    method reset (line 73) | def reset(self) -> Observation:
    method render (line 80) | def render(self, mode: str = "human", **kwargs) -> None:
    method close (line 83) | def close(self) -> None:

FILE: python/gym_ignition/scenario/model_with_file.py
  class ModelWithFile (line 8) | class ModelWithFile(abc.ABC):
    method __init__ (line 9) | def __init__(self):
    method get_model_file (line 15) | def get_model_file(cls) -> str:

FILE: python/gym_ignition/scenario/model_wrapper.py
  class ModelWrapper (line 10) | class ModelWrapper(scenario.Model, abc.ABC):
    method __init__ (line 11) | def __init__(self, model: scenario.Model):
    method __getattr__ (line 18) | def __getattr__(self, name):

FILE: python/gym_ignition/utils/logger.py
  function custom_formatwarning (line 14) | def custom_formatwarning(msg, *args, **kwargs):
  function warn (line 27) | def warn(msg: str, *args) -> None:
  function set_level (line 40) | def set_level(level: int, scenario_level: int = None) -> None:
  function gym_verbosity (line 82) | def gym_verbosity(level: int):

FILE: python/gym_ignition/utils/math.py
  function normalize (line 13) | def normalize(
  function denormalize (line 39) | def denormalize(

FILE: python/gym_ignition/utils/misc.py
  function string_to_file (line 8) | def string_to_file(string: str) -> str:

FILE: python/gym_ignition/utils/resource_finder.py
  function get_search_paths (line 14) | def get_search_paths() -> List[str]:
  function add_path (line 19) | def add_path(data_path: str) -> None:
  function add_path_from_env_var (line 37) | def add_path_from_env_var(env_variable: str) -> None:
  function find_resource (line 56) | def find_resource(file_name: str) -> str:

FILE: python/gym_ignition/utils/scenario.py
  function get_unique_model_name (line 15) | def get_unique_model_name(world: scenario.World, model_name: str) -> str:
  function init_gazebo_sim (line 49) | def init_gazebo_sim(
  function get_joint_positions_space (line 94) | def get_joint_positions_space(

FILE: python/gym_ignition_environments/models/cartpole.py
  class CartPole (line 13) | class CartPole(model_wrapper.ModelWrapper, model_with_file.ModelWithFile):
    method __init__ (line 14) | def __init__(
    method get_model_file (line 45) | def get_model_file(cls) -> str:

FILE: python/gym_ignition_environments/models/icub.py
  class ICubGazeboABC (line 14) | class ICubGazeboABC(
    method __init__ (line 63) | def __init__(
  class ICubGazebo (line 102) | class ICubGazebo(ICubGazeboABC):
    method __init__ (line 103) | def __init__(
    method get_model_file (line 119) | def get_model_file(cls) -> str:
  class ICubGazeboSimpleCollisions (line 126) | class ICubGazeboSimpleCollisions(ICubGazeboABC):
    method __init__ (line 127) | def __init__(
    method get_model_file (line 143) | def get_model_file(cls) -> str:

FILE: python/gym_ignition_environments/models/panda.py
  class Panda (line 13) | class Panda(model_wrapper.ModelWrapper, model_with_file.ModelWithFile):
    method __init__ (line 14) | def __init__(
    method get_model_file (line 78) | def get_model_file(cls) -> str:

FILE: python/gym_ignition_environments/models/pendulum.py
  class Pendulum (line 13) | class Pendulum(model_wrapper.ModelWrapper, model_with_file.ModelWithFile):
    method __init__ (line 14) | def __init__(
    method get_model_file (line 45) | def get_model_file(cls) -> str:

FILE: python/gym_ignition_environments/randomizers/cartpole.py
  class CartpoleRandomizersMixin (line 26) | class CartpoleRandomizersMixin(
    method __init__ (line 37) | def __init__(self, randomize_physics_after_rollouts: int = 0):
    method get_engine (line 53) | def get_engine(self):
    method randomize_physics (line 57) | def randomize_physics(self, task: SupportedTasks, **kwargs) -> None:
    method randomize_task (line 68) | def randomize_task(self, task: SupportedTasks, **kwargs) -> None:
    method randomize_model_description (line 96) | def randomize_model_description(self, task: SupportedTasks, **kwargs) ...
    method _get_sdf_randomizer (line 106) | def _get_sdf_randomizer(
    method _clean_world (line 144) | def _clean_world(task: SupportedTasks) -> None:
    method _populate_world (line 153) | def _populate_world(task: SupportedTasks, cartpole_model: str = None) ...
  class CartpoleEnvRandomizer (line 163) | class CartpoleEnvRandomizer(
    method __init__ (line 170) | def __init__(self, env: MakeEnvCallable, num_physics_rollouts: int = 0):

FILE: python/gym_ignition_environments/randomizers/cartpole_no_rand.py
  class CartpoleEnvNoRandomizations (line 20) | class CartpoleEnvNoRandomizations(gazebo_env_randomizer.GazeboEnvRandomi...
    method __init__ (line 28) | def __init__(self, env: MakeEnvCallable):
    method randomize_task (line 32) | def randomize_task(self, task: SupportedTasks, **kwargs) -> None:

FILE: python/gym_ignition_environments/tasks/cartpole_continuous_balancing.py
  class CartPoleContinuousBalancing (line 22) | class CartPoleContinuousBalancing(task.Task, abc.ABC):
    method __init__ (line 23) | def __init__(self, agent_rate: float, reward_cart_at_center: bool = Tr...
    method create_spaces (line 43) | def create_spaces(self) -> Tuple[ActionSpace, ObservationSpace]:
    method set_action (line 72) | def set_action(self, action: Action) -> None:
    method get_observation (line 84) | def get_observation(self) -> Observation:
    method get_reward (line 99) | def get_reward(self) -> Reward:
    method is_done (line 118) | def is_done(self) -> bool:
    method reset_task (line 128) | def reset_task(self) -> None:

FILE: python/gym_ignition_environments/tasks/cartpole_continuous_swingup.py
  class CartPoleContinuousSwingup (line 22) | class CartPoleContinuousSwingup(task.Task, abc.ABC):
    method __init__ (line 23) | def __init__(self, agent_rate: float, reward_cart_at_center: bool = Tr...
    method create_spaces (line 43) | def create_spaces(self) -> Tuple[ActionSpace, ObservationSpace]:
    method set_action (line 72) | def set_action(self, action: Action) -> None:
    method get_observation (line 84) | def get_observation(self) -> Observation:
    method get_reward (line 99) | def get_reward(self) -> Reward:
    method is_done (line 122) | def is_done(self) -> bool:
    method reset_task (line 132) | def reset_task(self) -> None:

FILE: python/gym_ignition_environments/tasks/cartpole_discrete_balancing.py
  class CartPoleDiscreteBalancing (line 22) | class CartPoleDiscreteBalancing(task.Task, abc.ABC):
    method __init__ (line 23) | def __init__(
    method create_spaces (line 46) | def create_spaces(self) -> Tuple[ActionSpace, ObservationSpace]:
    method set_action (line 72) | def set_action(self, action: Action) -> None:
    method get_observation (line 84) | def get_observation(self) -> Observation:
    method get_reward (line 99) | def get_reward(self) -> Reward:
    method is_done (line 118) | def is_done(self) -> bool:
    method reset_task (line 128) | def reset_task(self) -> None:

FILE: python/gym_ignition_environments/tasks/pendulum_swingup.py
  class PendulumSwingUp (line 22) | class PendulumSwingUp(task.Task, abc.ABC):
    method __init__ (line 23) | def __init__(self, agent_rate: float, **kwargs):
    method create_spaces (line 35) | def create_spaces(self) -> Tuple[ActionSpace, ObservationSpace]:
    method set_action (line 47) | def set_action(self, action: Action) -> None:
    method get_observation (line 59) | def get_observation(self) -> Observation:
    method get_reward (line 74) | def get_reward(self) -> Reward:
    method is_done (line 93) | def is_done(self) -> bool:
    method reset_task (line 103) | def reset_task(self) -> None:

FILE: scenario/bindings/__init__.py
  function supported_versions_specifier_set (line 14) | def supported_versions_specifier_set() -> packaging.specifiers.Specifier...
  class InstallMode (line 29) | class InstallMode(Enum):
  function detect_install_mode (line 35) | def detect_install_mode() -> InstallMode:
  function setup_gazebo_environment (line 53) | def setup_gazebo_environment() -> None:
  function preload_tensorflow_shared_libraries (line 86) | def preload_tensorflow_shared_libraries() -> None:
  function pre_import_gym (line 122) | def pre_import_gym() -> None:
  function check_gazebo_installation (line 135) | def check_gazebo_installation() -> None:
  function import_gazebo (line 178) | def import_gazebo() -> None:
  function create_home_dot_folder (line 212) | def create_home_dot_folder() -> None:

FILE: scenario/deps/clara/clara.hpp
  type clara (line 55) | namespace clara { namespace TextFlow {
    type TextFlow (line 55) | namespace TextFlow {
      function isWhitespace (line 57) | inline auto isWhitespace( char c ) -> bool {
      function isBreakableBefore (line 61) | inline auto isBreakableBefore( char c ) -> bool {
      function isBreakableAfter (line 65) | inline auto isBreakableAfter( char c ) -> bool {
      class Columns (line 70) | class Columns
        class iterator (line 253) | class iterator {
          type EndTag (line 255) | struct EndTag {}
          method iterator (line 261) | iterator( Columns const& columns, EndTag )
          method iterator (line 278) | explicit iterator( Columns const& columns )
        method begin (line 328) | auto begin() const -> iterator { return iterator( *this ); }
        method end (line 329) | auto end() const -> iterator { return { *this, iterator::EndTag() ...
        method friend (line 341) | inline friend std::ostream& operator << ( std::ostream& os, Column...
        method toString (line 354) | auto toString() const -> std::string {
      class Column (line 72) | class Column {
        class iterator (line 79) | class iterator {
          method iterator (line 90) | iterator( Column const& column, size_t stringIndex )
          method line (line 95) | auto line() const -> std::string const& { return m_column.m_stri...
          method isBoundary (line 97) | auto isBoundary( size_t at ) const -> bool {
          method calcLength (line 107) | void calcLength() {
          method indent (line 135) | auto indent() const -> size_t {
          method addIndentAndSuffix (line 140) | auto addIndentAndSuffix(std::string const &plain) const -> std::...
          method iterator (line 151) | explicit iterator( Column const& column ) : m_column( column ) {
        method Column (line 199) | explicit Column( std::string const& text ) { m_strings.push_back( ...
        method width (line 201) | auto width( size_t newWidth ) -> Column& {
        method indent (line 206) | auto indent( size_t newIndent ) -> Column& {
        method initialIndent (line 210) | auto initialIndent( size_t newIndent ) -> Column& {
        method width (line 215) | auto width() const -> size_t { return m_width; }
        method begin (line 216) | auto begin() const -> iterator { return iterator( *this ); }
        method end (line 217) | auto end() const -> iterator { return { *this, m_strings.size() }; }
        method friend (line 219) | inline friend std::ostream& operator << ( std::ostream& os, Column...
        method toString (line 233) | auto toString() const -> std::string {
      class Spacer (line 240) | class Spacer : public Column {
        method Spacer (line 243) | explicit Spacer( size_t spaceWidth ) : Column( "" ) {
      class Columns (line 248) | class Columns {
        class iterator (line 253) | class iterator {
          type EndTag (line 255) | struct EndTag {}
          method iterator (line 261) | iterator( Columns const& columns, EndTag )
          method iterator (line 278) | explicit iterator( Columns const& columns )
        method begin (line 328) | auto begin() const -> iterator { return iterator( *this ); }
        method end (line 329) | auto end() const -> iterator { return { *this, iterator::EndTag() ...
        method friend (line 341) | inline friend std::ostream& operator << ( std::ostream& os, Column...
        method toString (line 354) | auto toString() const -> std::string {
    type detail (line 384) | namespace detail {
      type UnaryLambdaTraits (line 388) | struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator(...
      type UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> (line 396) | struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
      class TokenStream (line 402) | class TokenStream
        method loadBuffer (line 450) | void loadBuffer() {
        method TokenStream (line 482) | explicit TokenStream( Args const &args ) : TokenStream( args.m_arg...
        method TokenStream (line 484) | TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEn...
        method count (line 492) | auto count() const -> size_t { return m_tokenBuffer.size() + (itEn...
      class Args (line 405) | class Args {
        method Args (line 411) | Args( int argc, char const* const* argv )
        method Args (line 415) | Args( std::initializer_list<std::string> args )
        method exeName (line 420) | auto exeName() const -> std::string {
      type TokenType (line 427) | enum class TokenType {
      type Token (line 430) | struct Token {
      function isOptPrefix (line 435) | inline auto isOptPrefix( char c ) -> bool {
      class TokenStream (line 444) | class TokenStream {
        method loadBuffer (line 450) | void loadBuffer() {
        method TokenStream (line 482) | explicit TokenStream( Args const &args ) : TokenStream( args.m_arg...
        method TokenStream (line 484) | TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEn...
        method count (line 492) | auto count() const -> size_t { return m_tokenBuffer.size() + (itEn...
      class ResultBase (line 517) | class ResultBase {
        type Type (line 519) | enum Type {
        method ResultBase (line 524) | ResultBase( Type type ) : m_type( type ) {}
      class ResultValueBase (line 533) | class ResultValueBase : public ResultBase {
        method value (line 535) | auto value() const -> T const & {
        method ResultValueBase (line 541) | ResultValueBase( Type type ) : ResultBase( type ) {}
        method ResultValueBase (line 543) | ResultValueBase( ResultValueBase const &other ) : ResultBase( othe...
        method ResultValueBase (line 548) | ResultValueBase( Type, T const &value ) : ResultBase( Ok ) {
      class ResultValueBase<void> (line 572) | class ResultValueBase<void> : public ResultBase {
      class BasicResult (line 578) | class BasicResult : public ResultValueBase<T> {
        method BasicResult (line 581) | explicit BasicResult( BasicResult<U> const &other )
        method ok (line 589) | static auto ok( U const &value ) -> BasicResult { return { ResultB...
        method ok (line 590) | static auto ok() -> BasicResult { return { ResultBase::Ok }; }
        method logicError (line 591) | static auto logicError( std::string const &message ) -> BasicResul...
        method runtimeError (line 592) | static auto runtimeError( std::string const &message ) -> BasicRes...
        method type (line 595) | auto type() const -> ResultBase::Type { return m_type; }
        method errorMessage (line 596) | auto errorMessage() const -> std::string { return m_errorMessage; }
        method enforceOk (line 599) | void enforceOk() const override {
        method BasicResult (line 611) | BasicResult( ResultBase::Type type, std::string const &message )
      type ParseResultType (line 622) | enum class ParseResultType {
      class ParseState (line 626) | class ParseState {
        method ParseState (line 629) | ParseState( ParseResultType type, TokenStream const &remainingToke...
        method type (line 634) | auto type() const -> ParseResultType { return m_type; }
        method remainingTokens (line 635) | auto remainingTokens() const -> TokenStream { return m_remainingTo...
      type HelpColumns (line 646) | struct HelpColumns {
      function convertInto (line 652) | inline auto convertInto( std::string const &source, T& target ) -> P...
      function convertInto (line 661) | inline auto convertInto( std::string const &source, std::string& tar...
      function convertInto (line 665) | inline auto convertInto( std::string const &source, bool &target ) -...
      function convertInto (line 678) | inline auto convertInto( std::string const &source, CLARA_CONFIG_OPT...
      type NonCopyable (line 687) | struct NonCopyable {
        method NonCopyable (line 688) | NonCopyable() = default;
        method NonCopyable (line 689) | NonCopyable( NonCopyable const & ) = delete;
        method NonCopyable (line 690) | NonCopyable( NonCopyable && ) = delete;
        method NonCopyable (line 691) | NonCopyable &operator=( NonCopyable const & ) = delete;
        method NonCopyable (line 692) | NonCopyable &operator=( NonCopyable && ) = delete;
      type BoundRef (line 695) | struct BoundRef : NonCopyable {
        method isContainer (line 697) | virtual auto isContainer() const -> bool { return false; }
        method isFlag (line 698) | virtual auto isFlag() const -> bool { return false; }
      type BoundValueRefBase (line 700) | struct BoundValueRefBase : BoundRef {
      type BoundFlagRefBase (line 703) | struct BoundFlagRefBase : BoundRef {
        method isFlag (line 705) | virtual auto isFlag() const -> bool { return true; }
      type BoundValueRef (line 709) | struct BoundValueRef : BoundValueRefBase {
        method BoundValueRef (line 712) | explicit BoundValueRef( T &ref ) : m_ref( ref ) {}
        method setValue (line 714) | auto setValue( std::string const &arg ) -> ParserResult override {
      type BoundValueRef<std::vector<T>> (line 720) | struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
        method BoundValueRef (line 723) | explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}
        method isContainer (line 725) | auto isContainer() const -> bool override { return true; }
        method setValue (line 727) | auto setValue( std::string const &arg ) -> ParserResult override {
      type BoundFlagRef (line 736) | struct BoundFlagRef : BoundFlagRefBase {
        method BoundFlagRef (line 739) | explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {}
        method setFlag (line 741) | auto setFlag( bool flag ) -> ParserResult override {
      type LambdaInvoker (line 748) | struct LambdaInvoker {
        method invoke (line 752) | static auto invoke( L const &lambda, ArgType const &arg ) -> Parse...
      type LambdaInvoker<void> (line 758) | struct LambdaInvoker<void> {
        method invoke (line 760) | static auto invoke( L const &lambda, ArgType const &arg ) -> Parse...
      function invokeLambda (line 767) | inline auto invokeLambda( L const &lambda, std::string const &arg ) ...
      type BoundLambda (line 777) | struct BoundLambda : BoundValueRefBase {
        method BoundLambda (line 781) | explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {}
        method setValue (line 783) | auto setValue( std::string const &arg ) -> ParserResult override {
      type BoundFlagLambda (line 789) | struct BoundFlagLambda : BoundFlagRefBase {
        method BoundFlagLambda (line 795) | explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {}
        method setFlag (line 797) | auto setFlag( bool flag ) -> ParserResult override {
      type Optionality (line 802) | enum class Optionality { Optional, Required }
      type Parser (line 804) | struct Parser
        method getHelpColumns (line 1111) | auto getHelpColumns() const -> std::vector<HelpColumns> {
        method writeToStream (line 1120) | void writeToStream( std::ostream &os ) const {
        method validate (line 1166) | auto validate() const -> Result override {
        method parse (line 1182) | auto parse( std::string const& exeName, TokenStream const &tokens ...
      class ParserBase (line 806) | class ParserBase {
        method validate (line 809) | virtual auto validate() const -> Result { return Result::ok(); }
        method cardinality (line 811) | virtual auto cardinality() const -> size_t { return 1; }
        method parse (line 813) | auto parse( Args const &args ) const -> InternalParseResult {
      class ComposableParserImpl (line 819) | class ComposableParserImpl : public ParserBase {
      class ParserRefImpl (line 830) | class ParserRefImpl : public ComposableParserImpl<DerivedT> {
        method ParserRefImpl (line 837) | explicit ParserRefImpl( std::shared_ptr<BoundRef> const &ref ) : m...
        method ParserRefImpl (line 841) | ParserRefImpl( T &ref, std::string const &hint )
        method ParserRefImpl (line 847) | ParserRefImpl( LambdaT const &ref, std::string const &hint )
        method optional (line 857) | auto optional() -> DerivedT & {
        method required (line 862) | auto required() -> DerivedT & {
        method isOptional (line 867) | auto isOptional() const -> bool {
        method cardinality (line 871) | auto cardinality() const -> size_t override {
        method hint (line 878) | auto hint() const -> std::string { return m_hint; }
      class ExeName (line 881) | class ExeName : public ComposableParserImpl<ExeName> {
        method makeRef (line 886) | static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<Boun...
        method ExeName (line 891) | ExeName() : m_name( std::make_shared<std::string>( "<executable>" ...
        method ExeName (line 893) | explicit ExeName( std::string &ref ) : ExeName() {
        method ExeName (line 898) | explicit ExeName( LambdaT const& lambda ) : ExeName() {
        method parse (line 903) | auto parse( std::string const&, TokenStream const &tokens ) const ...
        method name (line 907) | auto name() const -> std::string { return *m_name; }
        method set (line 908) | auto set( std::string const& newName ) -> ParserResult {
      class Arg (line 923) | class Arg : public ParserRefImpl<Arg> {
        method parse (line 927) | auto parse( std::string const &, TokenStream const &tokens ) const...
      function normaliseOpt (line 948) | inline auto normaliseOpt( std::string const &optName ) -> std::string {
      class Opt (line 957) | class Opt : public ParserRefImpl<Opt> {
        method Opt (line 963) | explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shar...
        method Opt (line 965) | explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared<BoundF...
        method Opt (line 968) | Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl...
        method Opt (line 971) | Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ...
        method getHelpColumns (line 978) | auto getHelpColumns() const -> std::vector<HelpColumns> {
        method isMatch (line 993) | auto isMatch( std::string const &optToken ) const -> bool {
        method parse (line 1004) | auto parse( std::string const&, TokenStream const &tokens ) const ...
        method validate (line 1040) | auto validate() const -> Result override {
      type Help (line 1058) | struct Help : Opt {
        method Help (line 1059) | Help( bool &showHelpFlag )
      type Parser (line 1073) | struct Parser : ParserBase {
        method getHelpColumns (line 1111) | auto getHelpColumns() const -> std::vector<HelpColumns> {
        method writeToStream (line 1120) | void writeToStream( std::ostream &os ) const {
        method validate (line 1166) | auto validate() const -> Result override {
        method parse (line 1182) | auto parse( std::string const& exeName, TokenStream const &tokens ...
  type clara (line 383) | namespace clara {
    type TextFlow (line 55) | namespace TextFlow {
      function isWhitespace (line 57) | inline auto isWhitespace( char c ) -> bool {
      function isBreakableBefore (line 61) | inline auto isBreakableBefore( char c ) -> bool {
      function isBreakableAfter (line 65) | inline auto isBreakableAfter( char c ) -> bool {
      class Columns (line 70) | class Columns
        class iterator (line 253) | class iterator {
          type EndTag (line 255) | struct EndTag {}
          method iterator (line 261) | iterator( Columns const& columns, EndTag )
          method iterator (line 278) | explicit iterator( Columns const& columns )
        method begin (line 328) | auto begin() const -> iterator { return iterator( *this ); }
        method end (line 329) | auto end() const -> iterator { return { *this, iterator::EndTag() ...
        method friend (line 341) | inline friend std::ostream& operator << ( std::ostream& os, Column...
        method toString (line 354) | auto toString() const -> std::string {
      class Column (line 72) | class Column {
        class iterator (line 79) | class iterator {
          method iterator (line 90) | iterator( Column const& column, size_t stringIndex )
          method line (line 95) | auto line() const -> std::string const& { return m_column.m_stri...
          method isBoundary (line 97) | auto isBoundary( size_t at ) const -> bool {
          method calcLength (line 107) | void calcLength() {
          method indent (line 135) | auto indent() const -> size_t {
          method addIndentAndSuffix (line 140) | auto addIndentAndSuffix(std::string const &plain) const -> std::...
          method iterator (line 151) | explicit iterator( Column const& column ) : m_column( column ) {
        method Column (line 199) | explicit Column( std::string const& text ) { m_strings.push_back( ...
        method width (line 201) | auto width( size_t newWidth ) -> Column& {
        method indent (line 206) | auto indent( size_t newIndent ) -> Column& {
        method initialIndent (line 210) | auto initialIndent( size_t newIndent ) -> Column& {
        method width (line 215) | auto width() const -> size_t { return m_width; }
        method begin (line 216) | auto begin() const -> iterator { return iterator( *this ); }
        method end (line 217) | auto end() const -> iterator { return { *this, m_strings.size() }; }
        method friend (line 219) | inline friend std::ostream& operator << ( std::ostream& os, Column...
        method toString (line 233) | auto toString() const -> std::string {
      class Spacer (line 240) | class Spacer : public Column {
        method Spacer (line 243) | explicit Spacer( size_t spaceWidth ) : Column( "" ) {
      class Columns (line 248) | class Columns {
        class iterator (line 253) | class iterator {
          type EndTag (line 255) | struct EndTag {}
          method iterator (line 261) | iterator( Columns const& columns, EndTag )
          method iterator (line 278) | explicit iterator( Columns const& columns )
        method begin (line 328) | auto begin() const -> iterator { return iterator( *this ); }
        method end (line 329) | auto end() const -> iterator { return { *this, iterator::EndTag() ...
        method friend (line 341) | inline friend std::ostream& operator << ( std::ostream& os, Column...
        method toString (line 354) | auto toString() const -> std::string {
    type detail (line 384) | namespace detail {
      type UnaryLambdaTraits (line 388) | struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator(...
      type UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> (line 396) | struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
      class TokenStream (line 402) | class TokenStream
        method loadBuffer (line 450) | void loadBuffer() {
        method TokenStream (line 482) | explicit TokenStream( Args const &args ) : TokenStream( args.m_arg...
        method TokenStream (line 484) | TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEn...
        method count (line 492) | auto count() const -> size_t { return m_tokenBuffer.size() + (itEn...
      class Args (line 405) | class Args {
        method Args (line 411) | Args( int argc, char const* const* argv )
        method Args (line 415) | Args( std::initializer_list<std::string> args )
        method exeName (line 420) | auto exeName() const -> std::string {
      type TokenType (line 427) | enum class TokenType {
      type Token (line 430) | struct Token {
      function isOptPrefix (line 435) | inline auto isOptPrefix( char c ) -> bool {
      class TokenStream (line 444) | class TokenStream {
        method loadBuffer (line 450) | void loadBuffer() {
        method TokenStream (line 482) | explicit TokenStream( Args const &args ) : TokenStream( args.m_arg...
        method TokenStream (line 484) | TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEn...
        method count (line 492) | auto count() const -> size_t { return m_tokenBuffer.size() + (itEn...
      class ResultBase (line 517) | class ResultBase {
        type Type (line 519) | enum Type {
        method ResultBase (line 524) | ResultBase( Type type ) : m_type( type ) {}
      class ResultValueBase (line 533) | class ResultValueBase : public ResultBase {
        method value (line 535) | auto value() const -> T const & {
        method ResultValueBase (line 541) | ResultValueBase( Type type ) : ResultBase( type ) {}
        method ResultValueBase (line 543) | ResultValueBase( ResultValueBase const &other ) : ResultBase( othe...
        method ResultValueBase (line 548) | ResultValueBase( Type, T const &value ) : ResultBase( Ok ) {
      class ResultValueBase<void> (line 572) | class ResultValueBase<void> : public ResultBase {
      class BasicResult (line 578) | class BasicResult : public ResultValueBase<T> {
        method BasicResult (line 581) | explicit BasicResult( BasicResult<U> const &other )
        method ok (line 589) | static auto ok( U const &value ) -> BasicResult { return { ResultB...
        method ok (line 590) | static auto ok() -> BasicResult { return { ResultBase::Ok }; }
        method logicError (line 591) | static auto logicError( std::string const &message ) -> BasicResul...
        method runtimeError (line 592) | static auto runtimeError( std::string const &message ) -> BasicRes...
        method type (line 595) | auto type() const -> ResultBase::Type { return m_type; }
        method errorMessage (line 596) | auto errorMessage() const -> std::string { return m_errorMessage; }
        method enforceOk (line 599) | void enforceOk() const override {
        method BasicResult (line 611) | BasicResult( ResultBase::Type type, std::string const &message )
      type ParseResultType (line 622) | enum class ParseResultType {
      class ParseState (line 626) | class ParseState {
        method ParseState (line 629) | ParseState( ParseResultType type, TokenStream const &remainingToke...
        method type (line 634) | auto type() const -> ParseResultType { return m_type; }
        method remainingTokens (line 635) | auto remainingTokens() const -> TokenStream { return m_remainingTo...
      type HelpColumns (line 646) | struct HelpColumns {
      function convertInto (line 652) | inline auto convertInto( std::string const &source, T& target ) -> P...
      function convertInto (line 661) | inline auto convertInto( std::string const &source, std::string& tar...
      function convertInto (line 665) | inline auto convertInto( std::string const &source, bool &target ) -...
      function convertInto (line 678) | inline auto convertInto( std::string const &source, CLARA_CONFIG_OPT...
      type NonCopyable (line 687) | struct NonCopyable {
        method NonCopyable (line 688) | NonCopyable() = default;
        method NonCopyable (line 689) | NonCopyable( NonCopyable const & ) = delete;
        method NonCopyable (line 690) | NonCopyable( NonCopyable && ) = delete;
        method NonCopyable (line 691) | NonCopyable &operator=( NonCopyable const & ) = delete;
        method NonCopyable (line 692) | NonCopyable &operator=( NonCopyable && ) = delete;
      type BoundRef (line 695) | struct BoundRef : NonCopyable {
        method isContainer (line 697) | virtual auto isContainer() const -> bool { return false; }
        method isFlag (line 698) | virtual auto isFlag() const -> bool { return false; }
      type BoundValueRefBase (line 700) | struct BoundValueRefBase : BoundRef {
      type BoundFlagRefBase (line 703) | struct BoundFlagRefBase : BoundRef {
        method isFlag (line 705) | virtual auto isFlag() const -> bool { return true; }
      type BoundValueRef (line 709) | struct BoundValueRef : BoundValueRefBase {
        method BoundValueRef (line 712) | explicit BoundValueRef( T &ref ) : m_ref( ref ) {}
        method setValue (line 714) | auto setValue( std::string const &arg ) -> ParserResult override {
      type BoundValueRef<std::vector<T>> (line 720) | struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
        method BoundValueRef (line 723) | explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}
        method isContainer (line 725) | auto isContainer() const -> bool override { return true; }
        method setValue (line 727) | auto setValue( std::string const &arg ) -> ParserResult override {
      type BoundFlagRef (line 736) | struct BoundFlagRef : BoundFlagRefBase {
        method BoundFlagRef (line 739) | explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {}
        method setFlag (line 741) | auto setFlag( bool flag ) -> ParserResult override {
      type LambdaInvoker (line 748) | struct LambdaInvoker {
        method invoke (line 752) | static auto invoke( L const &lambda, ArgType const &arg ) -> Parse...
      type LambdaInvoker<void> (line 758) | struct LambdaInvoker<void> {
        method invoke (line 760) | static auto invoke( L const &lambda, ArgType const &arg ) -> Parse...
      function invokeLambda (line 767) | inline auto invokeLambda( L const &lambda, std::string const &arg ) ...
      type BoundLambda (line 777) | struct BoundLambda : BoundValueRefBase {
        method BoundLambda (line 781) | explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {}
        method setValue (line 783) | auto setValue( std::string const &arg ) -> ParserResult override {
      type BoundFlagLambda (line 789) | struct BoundFlagLambda : BoundFlagRefBase {
        method BoundFlagLambda (line 795) | explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {}
        method setFlag (line 797) | auto setFlag( bool flag ) -> ParserResult override {
      type Optionality (line 802) | enum class Optionality { Optional, Required }
      type Parser (line 804) | struct Parser
        method getHelpColumns (line 1111) | auto getHelpColumns() const -> std::vector<HelpColumns> {
        method writeToStream (line 1120) | void writeToStream( std::ostream &os ) const {
        method validate (line 1166) | auto validate() const -> Result override {
        method parse (line 1182) | auto parse( std::string const& exeName, TokenStream const &tokens ...
      class ParserBase (line 806) | class ParserBase {
        method validate (line 809) | virtual auto validate() const -> Result { return Result::ok(); }
        method cardinality (line 811) | virtual auto cardinality() const -> size_t { return 1; }
        method parse (line 813) | auto parse( Args const &args ) const -> InternalParseResult {
      class ComposableParserImpl (line 819) | class ComposableParserImpl : public ParserBase {
      class ParserRefImpl (line 830) | class ParserRefImpl : public ComposableParserImpl<DerivedT> {
        method ParserRefImpl (line 837) | explicit ParserRefImpl( std::shared_ptr<BoundRef> const &ref ) : m...
        method ParserRefImpl (line 841) | ParserRefImpl( T &ref, std::string const &hint )
        method ParserRefImpl (line 847) | ParserRefImpl( LambdaT const &ref, std::string const &hint )
        method optional (line 857) | auto optional() -> DerivedT & {
        method required (line 862) | auto required() -> DerivedT & {
        method isOptional (line 867) | auto isOptional() const -> bool {
        method cardinality (line 871) | auto cardinality() const -> size_t override {
        method hint (line 878) | auto hint() const -> std::string { return m_hint; }
      class ExeName (line 881) | class ExeName : public ComposableParserImpl<ExeName> {
        method makeRef (line 886) | static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<Boun...
        method ExeName (line 891) | ExeName() : m_name( std::make_shared<std::string>( "<executable>" ...
        method ExeName (line 893) | explicit ExeName( std::string &ref ) : ExeName() {
        method ExeName (line 898) | explicit ExeName( LambdaT const& lambda ) : ExeName() {
        method parse (line 903) | auto parse( std::string const&, TokenStream const &tokens ) const ...
        method name (line 907) | auto name() const -> std::string { return *m_name; }
        method set (line 908) | auto set( std::string const& newName ) -> ParserResult {
      class Arg (line 923) | class Arg : public ParserRefImpl<Arg> {
        method parse (line 927) | auto parse( std::string const &, TokenStream const &tokens ) const...
      function normaliseOpt (line 948) | inline auto normaliseOpt( std::string const &optName ) -> std::string {
      class Opt (line 957) | class Opt : public ParserRefImpl<Opt> {
        method Opt (line 963) | explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shar...
        method Opt (line 965) | explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared<BoundF...
        method Opt (line 968) | Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl...
        method Opt (line 971) | Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ...
        method getHelpColumns (line 978) | auto getHelpColumns() const -> std::vector<HelpColumns> {
        method isMatch (line 993) | auto isMatch( std::string const &optToken ) const -> bool {
        method parse (line 1004) | auto parse( std::string const&, TokenStream const &tokens ) const ...
        method validate (line 1040) | auto validate() const -> Result override {
      type Help (line 1058) | struct Help : Opt {
        method Help (line 1059) | Help( bool &showHelpFlag )
      type Parser (line 1073) | struct Parser : ParserBase {
        method getHelpColumns (line 1111) | auto getHelpColumns() const -> std::vector<HelpColumns> {
        method writeToStream (line 1120) | void writeToStream( std::ostream &os ) const {
        method validate (line 1166) | auto validate() const -> Result override {
        method parse (line 1182) | auto parse( std::string const& exeName, TokenStream const &tokens ...
  type UnaryLambdaTraits<ReturnT( ClassT::* )( Args... ) const> (line 391) | struct UnaryLambdaTraits<ReturnT( ClassT::* )( Args... ) const> {

FILE: scenario/src/controllers/include/scenario/controllers/ComputedTorqueFixedBase.h
  function namespace (line 20) | namespace scenario::core {
  function namespace (line 24) | namespace scenario::controllers {

FILE: scenario/src/controllers/include/scenario/controllers/Controller.h
  function namespace (line 19) | namespace scenario::controllers {
  function namespace (line 28) | namespace scenario::core {
  function class (line 47) | class scenario::controllers::UseScenarioModel
  function class (line 59) | class scenario::controllers::SetBaseReferences
  function class (line 68) | class scenario::controllers::SetJointReferences

FILE: scenario/src/controllers/include/scenario/controllers/References.h
  function namespace (line 16) | namespace scenario::controllers {
  function BaseReferences (line 21) | struct scenario::controllers::BaseReferences
  function JointReferences (line 31) | struct scenario::controllers::JointReferences

FILE: scenario/src/controllers/src/ComputedTorqueFixedBase.cpp
  class ComputedTorqueFixedBase::Impl (line 29) | class ComputedTorqueFixedBase::Impl
    class Buffers (line 32) | class Buffers
    method toEigen (line 48) | static Eigen::Map<Eigen::VectorXd> toEigen(std::vector<double>& vector)
  class ComputedTorqueFixedBase::Impl::Buffers (line 54) | class ComputedTorqueFixedBase::Impl::Buffers
    method Buffers (line 57) | Buffers(const unsigned controlledDofs = 0)

FILE: scenario/src/core/include/scenario/core/Joint.h
  type PID (line 18) | struct PID
  type Limit (line 19) | struct Limit
  type JointLimit (line 20) | struct JointLimit
  function JointType (line 25) | enum class JointType

FILE: scenario/src/core/include/scenario/core/Link.h
  function namespace (line 17) | namespace scenario::core {
  function class (line 25) | class scenario::core::Link
  function Pose (line 188) | struct scenario::core::Pose
  function ContactPoint (line 214) | struct scenario::core::ContactPoint
  function Contact (line 223) | struct scenario::core::Contact

FILE: scenario/src/core/include/scenario/core/Model.h
  function namespace (line 19) | namespace scenario::core {
  function class (line 28) | class scenario::core::Model

FILE: scenario/src/core/include/scenario/core/World.h
  function namespace (line 18) | namespace scenario::core {
  function class (line 25) | class scenario::core::World

FILE: scenario/src/core/include/scenario/core/utils/signals.h
  function namespace (line 15) | namespace scenario::core::utils {
  function class (line 19) | class scenario::core::utils::SignalManager

FILE: scenario/src/core/include/scenario/core/utils/utils.h
  function namespace (line 14) | namespace scenario::core::utils {

FILE: scenario/src/core/src/signals.cpp
  type scenario::core::detail (line 16) | namespace scenario::core::detail {
  class SignalManager::Impl (line 22) | class SignalManager::Impl
  function SignalManager (line 54) | SignalManager& SignalManager::Instance()

FILE: scenario/src/gazebo/include/scenario/gazebo/GazeboEntity.h
  function namespace (line 36) | namespace scenario::gazebo {
  function class (line 40) | class scenario::gazebo::GazeboEntity

FILE: scenario/src/gazebo/include/scenario/gazebo/GazeboSimulator.h
  function namespace (line 36) | namespace scenario::gazebo {
  function class (line 41) | class scenario::gazebo::GazeboSimulator

FILE: scenario/src/gazebo/include/scenario/gazebo/Joint.h
  function namespace (line 41) | namespace scenario::gazebo {

FILE: scenario/src/gazebo/include/scenario/gazebo/Link.h
  function namespace (line 43) | namespace scenario::gazebo {

FILE: scenario/src/gazebo/include/scenario/gazebo/Model.h
  function namespace (line 42) | namespace scenario::gazebo {

FILE: scenario/src/gazebo/include/scenario/gazebo/World.h
  function namespace (line 42) | namespace scenario::gazebo {

FILE: scenario/src/gazebo/include/scenario/gazebo/components/BasePoseTarget.h
  function namespace (line 35) | namespace ignition::gazebo {

FILE: scenario/src/gazebo/include/scenario/gazebo/components/BaseWorldAccelerationTarget.h
  function namespace (line 36) | namespace ignition::gazebo {

FILE: scenario/src/gazebo/include/scenario/gazebo/components/BaseWorldVelocityTarget.h
  function namespace (line 36) | namespace ignition::gazebo {

FILE: scenario/src/gazebo/include/scenario/gazebo/components/ExternalWorldWrenchCmdWithDuration.h
  function namespace (line 38) | namespace ignition::gazebo {

FILE: scenario/src/gazebo/include/scenario/gazebo/components/HistoryOfAppliedJointForces.h
  function namespace (line 36) | namespace ignition::gazebo {

FILE: scenario/src/gazebo/include/scenario/gazebo/components/JointAcceleration.h
  function namespace (line 37) | namespace ignition {

FILE: scenario/src/gazebo/include/scenario/gazebo/components/JointAccelerationTarget.h
  function namespace (line 37) | namespace ignition::gazebo {

FILE: scenario/src/gazebo/include/scenario/gazebo/components/JointControlMode.h
  function namespace (line 36) | namespace ignition::gazebo {

FILE: scenario/src/gazebo/include/scenario/gazebo/components/JointController.h
  function namespace (line 34) | namespace ignition::gazebo {

FILE: scenario/src/gazebo/include/scenario/gazebo/components/JointControllerPeriod.h
  function namespace (line 37) | namespace ignition::gazebo {

FILE: scenario/src/gazebo/include/scenario/gazebo/components/JointPID.h
  function namespace (line 35) | namespace ignition::gazebo {

FILE: scenario/src/gazebo/include/scenario/gazebo/components/JointPositionTarget.h
  function namespace (line 36) | namespace ignition::gazebo {

FILE: scenario/src/gazebo/include/scenario/gazebo/components/JointVelocityTarget.h
  function namespace (line 37) | namespace ignition::gazebo {

FILE: scenario/src/gazebo/include/scenario/gazebo/components/SimulatedTime.h
  function namespace (line 36) | namespace ignition::gazebo {

FILE: scenario/src/gazebo/include/scenario/gazebo/components/Timestamp.h
  function namespace (line 36) | namespace ignition::gazebo {

FILE: scenario/src/gazebo/include/scenario/gazebo/exceptions.h
  function namespace (line 38) | namespace scenario::gazebo {

FILE: scenario/src/gazebo/include/scenario/gazebo/helpers.h
  function namespace (line 62) | namespace scenario::gazebo::utils {
  function ignition (line 244) | static inline ignition::math::Vector3d
  function ignition (line 250) | static inline ignition::math::Vector4d
  function ignition (line 256) | static inline ignition::math::Quaterniond
  function ignition (line 262) | static inline ignition::math::PID
  function scenario (line 275) | static inline scenario::core::PID
  function class (line 288) | class WrenchWithDuration
  function class (line 347) | class LinkWrenchCmd

FILE: scenario/src/gazebo/include/scenario/gazebo/utils.h
  function namespace (line 41) | namespace scenario::base {
  function namespace (line 45) | namespace scenario::gazebo {
  function Verbosity (line 50) | enum class Verbosity

FILE: scenario/src/gazebo/src/GazeboSimulator.cpp
  type scenario::gazebo::detail (line 63) | namespace scenario::gazebo::detail {
    class ECMProvider (line 64) | class ECMProvider
    type PhysicsData (line 65) | struct PhysicsData
    type SimulationResources (line 66) | struct SimulationResources
  type detail::PhysicsData (line 73) | struct detail::PhysicsData
    method valid (line 79) | bool valid() const { return this->rtf > 0 && this->maxStepSize > 0; }
  class scenario::gazebo::detail::ECMProvider (line 82) | class scenario::gazebo::detail::ECMProvider final
    method ECMProvider (line 87) | ECMProvider()
  class GazeboSimulator::Impl (line 105) | class GazeboSimulator::Impl

FILE: scenario/src/gazebo/src/Joint.cpp
  class Joint::Impl (line 66) | class Joint::Impl

FILE: scenario/src/gazebo/src/Link.cpp
  class Link::Impl (line 61) | class Link::Impl
    method GetWorldPose (line 66) | static ignition::math::Pose3d GetWorldPose(const Link& link,

FILE: scenario/src/gazebo/src/Model.cpp
  class Model::Impl (line 68) | class Model::Impl

FILE: scenario/src/gazebo/src/World.cpp
  class World::Impl (line 60) | class World::Impl
    method insertModel (line 74) | bool insertModel(const std::shared_ptr<sdf::Root>& modelSdfRoot,

FILE: scenario/src/gazebo/src/helpers.cpp
  type scenario::gazebo::utils (line 361) | namespace scenario::gazebo::utils {

FILE: scenario/src/plugins/ControllerRunner/ControllerRunner.cpp
  class ControllerRunner::Impl (line 57) | class ControllerRunner::Impl

FILE: scenario/src/plugins/ControllerRunner/ControllerRunner.h
  function namespace (line 38) | namespace scenario::plugins::gazebo {

FILE: scenario/src/plugins/ControllerRunner/ControllersFactory.cpp
  class ControllersFactory::Impl (line 44) | class ControllersFactory::Impl
  function T (line 155) | T ControllersFactory::Impl::GetElementValueAs(

FILE: scenario/src/plugins/ControllerRunner/ControllersFactory.h
  function namespace (line 37) | namespace scenario::plugins::gazebo {
  function class (line 41) | class scenario::plugins::gazebo::ControllersFactory

FILE: scenario/src/plugins/JointController/JointController.cpp
  class JointController::Impl (line 56) | class JointController::Impl

FILE: scenario/src/plugins/JointController/JointController.h
  function namespace (line 38) | namespace scenario::plugins::gazebo {

FILE: scenario/src/plugins/Physics/CanonicalLinkModelTracker.hh
  type ignition::gazebo (line 29) | namespace ignition::gazebo
    type IGNITION_GAZEBO_VERSION_NAMESPACE (line 31) | inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
      type systems::physics_system (line 32) | namespace systems::physics_system
        class CanonicalLinkModelTracker (line 55) | class CanonicalLinkModelTracker

FILE: scenario/src/plugins/Physics/EntityFeatureMap.hh
  type ignition::gazebo (line 32) | namespace ignition::gazebo
    type IGNITION_GAZEBO_VERSION_NAMESPACE (line 34) | inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
      type systems::physics_system (line 35) | namespace systems::physics_system
        class EntityFeatureMap (line 63) | class EntityFeatureMap
          method EntityCast (line 96) | PhysicsEntityPtr<ToFeatureList>
          method EntityCast (line 150) | PhysicsEntityPtr<ToFeatureList>
          method RequiredEntityPtr (line 166) | RequiredEntityPtr Get(const Entity &_entity) const
          method Entity (line 181) | Entity Get(const RequiredEntityPtr &_physEntity) const
          method RequiredEntityPtr (line 196) | RequiredEntityPtr GetPhysicsEntityPtr(std::size_t _id) const
          method HasEntity (line 211) | bool HasEntity(const Entity &_entity) const
          method HasEntity (line 221) | bool HasEntity(const RequiredEntityPtr &_physicsEntity) const
          method AddEntity (line 229) | void AddEntity(const Entity &_entity,
          method Remove (line 240) | bool Remove(Entity _entity)
          method Remove (line 257) | bool Remove(const RequiredEntityPtr &_physicsEntity)
          method TotalMapEntryCount (line 282) | std::size_t TotalMapEntryCount() const

FILE: scenario/src/plugins/Physics/Physics.cc
  class ignition::gazebo::systems::PhysicsPrivate (line 151) | class ignition::gazebo::systems::PhysicsPrivate
    type MinimumFeatureList (line 157) | struct MinimumFeatureList : ignition::physics::FeatureList<
    type FrictionPyramidSlipComplianceFeatureList (line 418) | struct FrictionPyramidSlipComplianceFeatureList
    type JointFeatureList (line 427) | struct JointFeatureList : ignition::physics::FeatureList<
    type DetachableJointFeatureList (line 439) | struct DetachableJointFeatureList : physics::FeatureList<
    type JointGetTransmittedWrenchFeatureList (line 448) | struct JointGetTransmittedWrenchFeatureList : physics::FeatureList<
    type CollisionFeatureList (line 455) | struct CollisionFeatureList : ignition::physics::FeatureList<
    type CollisionMaskFeatureList (line 472) | struct CollisionMaskFeatureList : ignition::physics::FeatureList<
    type LinkForceFeatureList (line 479) | struct LinkForceFeatureList : ignition::physics::FeatureList<
    type BoundingBoxFeatureList (line 486) | struct BoundingBoxFeatureList : ignition::physics::FeatureList<
    type JointVelocityCommandFeatureList (line 494) | struct JointVelocityCommandFeatureList : physics::FeatureList<
    type WorldVelocityCommandFeatureList (line 499) | struct WorldVelocityCommandFeatureList :
    type MeshFeatureList (line 510) | struct MeshFeatureList : physics::FeatureList<
    type HeightmapFeatureList (line 520) | struct HeightmapFeatureList : ignition::physics::FeatureList<
    type CollisionDetectorFeatureList (line 527) | struct CollisionDetectorFeatureList : ignition::physics::FeatureList<
    type SolverFeatureList (line 533) | struct SolverFeatureList : ignition::physics::FeatureList<
    type NestedModelFeatureList (line 540) | struct NestedModelFeatureList : ignition::physics::FeatureList<
  type AllContactData (line 3143) | struct AllContactData

FILE: scenario/src/plugins/Physics/Physics.hh
  type ignition (line 55) | namespace ignition
    type gazebo (line 57) | namespace gazebo
      type IGNITION_GAZEBO_VERSION_NAMESPACE (line 60) | inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
        type systems (line 61) | namespace systems
          class PhysicsPrivate (line 64) | class PhysicsPrivate
          class Physics (line 68) | class Physics:

FILE: tests/.python/test_contacts.py
  function test_contacts (line 12) | def test_contacts():

FILE: tests/.python/test_environments_gazebowrapper.py
  function template_run_environment (line 13) | def template_run_environment(env_name):
  function test_environment (line 40) | def test_environment(env_name: str):

FILE: tests/.python/test_externalforce.py
  function test_external_force (line 12) | def test_external_force():

FILE: tests/.python/test_joint_force.py
  function test_joint_force (line 10) | def test_joint_force():
  function test_joint_force_multiple_iterations (line 49) | def test_joint_force_multiple_iterations():

FILE: tests/.python/test_pendulum_wrt_ground_truth.py
  class PendulumEnv (line 19) | class PendulumEnv(gym.Env):
    method __init__ (line 27) | def __init__(self):
    method set_state_from_obs (line 42) | def set_state_from_obs(self, observation: np.ndarray) -> None:
    method step (line 54) | def step(self, action: np.ndarray) -> State:
    method reset (line 71) | def reset(self):
    method render (line 75) | def render(self, mode="human", **kwargs):
    method seed (line 78) | def seed(self, seed=None):
  function theta_from_obs (line 82) | def theta_from_obs(observation: np.ndarray) -> float:
  function template_pendulum_wrt_ground_truth (line 122) | def template_pendulum_wrt_ground_truth(env_name: str, max_error_in_deg: ...
  function test_pendulum_ignition (line 188) | def test_pendulum_ignition(env_name: str, max_error_in_deg: float):

FILE: tests/.python/test_rates.py
  function almost_equal (line 17) | def almost_equal(first, second, epsilon=None) -> bool:
  function template_test (line 36) | def template_test(
  function create_test_matrix (line 121) | def create_test_matrix() -> List[Tuple[float, float, float]]:
  function test_rates (line 148) | def test_rates(rtf: float, agent_rate: float, physics_rate: float):

FILE: tests/.python/test_robot_base.py
  function test_robot_fixed_base (line 12) | def test_robot_fixed_base(simulator_name: str):
  function test_robot_floating_to_fixed (line 61) | def test_robot_floating_to_fixed(simulator_name: str):

FILE: tests/.python/test_robot_controller.py
  function test_joint_controller (line 11) | def test_joint_controller():

FILE: tests/.python/test_runtimes.py
  function template_compare_environments (line 91) | def template_compare_environments(env_name_a: str, env_name_b: str, max_...
  function test_compare_environments (line 168) | def test_compare_environments(env_name_a: str, env_name_b: str, max_erro...

FILE: tests/.python/utils.py
  class Simulator (line 17) | class Simulator(abc.ABC):
    method step (line 22) | def step(self):
    method close (line 26) | def close(self):
  class Gazebo (line 30) | class Gazebo(Simulator):
    method __init__ (line 33) | def __init__(
    method step (line 51) | def step(self):
    method close (line 57) | def close(self):
  class PyBullet (line 62) | class PyBullet(Simulator):
    method __init__ (line 65) | def __init__(self, physics_rate: float):
    method step (line 76) | def step(self):
    method close (line 79) | def close(self):
  function get_pendulum (line 84) | def get_pendulum(simulator: Simulator, **kwargs):
  function get_cartpole (line 97) | def get_cartpole(simulator: Simulator, **kwargs):
  class CubeGazeboRobot (line 110) | class CubeGazeboRobot(gazebo_robot.GazeboRobot):
    method __init__ (line 111) | def __init__(self, gazebo, initial_position: np.ndarray, model_file: s...
  function get_cube_urdf (line 135) | def get_cube_urdf() -> str:

FILE: tests/common/utils.py
  function id_gazebo_fn (line 15) | def id_gazebo_fn(val: Tuple[float, float, float]):
  function gazebo_fixture (line 21) | def gazebo_fixture(request):
  function default_world_fixture (line 57) | def default_world_fixture(request):
  function get_multi_world_sdf_file (line 88) | def get_multi_world_sdf_file() -> str:
  function get_cube_sdf_string (line 103) | def get_cube_sdf_string() -> str:
  function get_cube_urdf_string (line 152) | def get_cube_urdf_string() -> str:
  function get_cube_urdf (line 183) | def get_cube_urdf() -> str:
  function get_empty_world_sdf (line 189) | def get_empty_world_sdf() -> str:
  class SphereURDF (line 198) | class SphereURDF:
    method urdf (line 204) | def urdf(self) -> str:

FILE: tests/test_gym_ignition/test_inverse_kinematics.py
  function test_inverse_kinematics (line 25) | def test_inverse_kinematics(

FILE: tests/test_gym_ignition/test_normalization.py
  function test_normalization (line 31) | def test_normalization(input, low, high, output):

FILE: tests/test_gym_ignition/test_reproducibility.py
  function make_env (line 17) | def make_env(**kwargs) -> gym.Env:
  function test_reproducibility (line 26) | def test_reproducibility(num_physics_rollouts: int):

FILE: tests/test_gym_ignition/test_sdf_randomizer.py
  function test_sdf_randomizer (line 23) | def test_sdf_randomizer():
  function test_randomizer_reproducibility (line 80) | def test_randomizer_reproducibility():
  function test_randomize_missing_element (line 139) | def test_randomize_missing_element():
  function test_full_panda_randomization (line 197) | def test_full_panda_randomization():

FILE: tests/test_scenario/test_contacts.py
  function get_cube_urdf_string_double_collision (line 25) | def get_cube_urdf_string_double_collision() -> str:
  function test_cube_contact (line 71) | def test_cube_contact(gazebo: scenario.GazeboSimulator, get_model_str: C...
  function test_cube_multiple_contacts (line 142) | def test_cube_multiple_contacts(

FILE: tests/test_scenario/test_custom_controllers.py
  function test_computed_torque_fixed_base (line 26) | def test_computed_torque_fixed_base(gazebo: scenario.GazeboSimulator):

FILE: tests/test_scenario/test_external_wrench.py
  function test_fixed_base (line 24) | def test_fixed_base(default_world: Tuple[scenario.GazeboSimulator, scena...

FILE: tests/test_scenario/test_gazebo_simulator.py
  function test_initialization (line 33) | def test_initialization(gazebo: scenario.GazeboSimulator):
  function test_run (line 64) | def test_run(gazebo: scenario.GazeboSimulator):
  function test_pause (line 74) | def test_pause(gazebo: scenario.GazeboSimulator):
  function test_paused_step (line 97) | def test_paused_step(gazebo: scenario.GazeboSimulator):
  function test_load_default_world (line 117) | def test_load_default_world(gazebo: scenario.GazeboSimulator):

FILE: tests/test_scenario/test_ignition_fuel.py
  function test_download_model_from_fuel (line 26) | def test_download_model_from_fuel(gazebo: scenario.GazeboSimulator):
  function test_fuel_world (line 55) | def test_fuel_world(gazebo: scenario.GazeboSimulator):

FILE: tests/test_scenario/test_link_velocities.py
  function to_wxyz (line 26) | def to_wxyz(xyzw: np.ndarray) -> np.ndarray:
  function to_xyzw (line 34) | def to_xyzw(wxyz: np.ndarray) -> np.ndarray:
  function to_matrix (line 42) | def to_matrix(quaternion: Tuple[float, float, float, float]) -> np.ndarray:
  function get_random_panda (line 48) | def get_random_panda(
  function get_cube (line 71) | def get_cube(gazebo: scenario.GazeboSimulator, world: scenario.World) ->...
  function test_linear_velocity (line 98) | def test_linear_velocity(
  function test_angular_velocity (line 159) | def test_angular_velocity(
  function test_linear_acceleration (line 221) | def test_linear_acceleration(
  function test_angular_acceleration (line 288) | def test_angular_acceleration(

FILE: tests/test_scenario/test_model.py
  function get_model (line 25) | def get_model(
  function test_model_core_api (line 51) | def test_model_core_api(gazebo: scenario.GazeboSimulator):
  function test_model_joints (line 72) | def test_model_joints(gazebo: scenario.GazeboSimulator):
  function test_model_base_pose (line 123) | def test_model_base_pose(gazebo: scenario.GazeboSimulator):
  function test_model_base_velocity (line 159) | def test_model_base_velocity(
  function test_model_references (line 232) | def test_model_references(gazebo: scenario.GazeboSimulator):
  function test_history_of_joint_forces (line 276) | def test_history_of_joint_forces(

FILE: tests/test_scenario/test_multi_world.py
  function test_insert_multiple_worlds (line 26) | def test_insert_multiple_worlds(gazebo: scenario_gazebo.GazeboSimulator):
  function test_insert_multiple_world (line 49) | def test_insert_multiple_world(gazebo: scenario_gazebo.GazeboSimulator):
  function test_insert_multiple_world_rename (line 71) | def test_insert_multiple_world_rename(gazebo: scenario_gazebo.GazeboSimu...
  function test_insert_world_multiple_calls (line 94) | def test_insert_world_multiple_calls(gazebo: scenario_gazebo.GazeboSimul...

FILE: tests/test_scenario/test_pid_controllers.py
  function test_position_pid (line 38) | def test_position_pid(default_world: Tuple[scenario.GazeboSimulator, sce...

FILE: tests/test_scenario/test_velocity_direct.py
  function test_velocity_direct (line 24) | def test_velocity_direct(

FILE: tests/test_scenario/test_world.py
  function test_load_default_world (line 22) | def test_load_default_world(gazebo: scenario.GazeboSimulator):
  function test_load_default_world_from_file (line 35) | def test_load_default_world_from_file(gazebo: scenario.GazeboSimulator):
  function test_rename_default_world (line 52) | def test_rename_default_world(gazebo: scenario.GazeboSimulator):
  function test_world_api (line 74) | def test_world_api(gazebo: scenario.GazeboSimulator):
  function test_world_physics_plugin (line 155) | def test_world_physics_plugin(gazebo: scenario.GazeboSimulator):
  function test_sim_time_starts_from_zero (line 201) | def test_sim_time_starts_from_zero(gazebo: scenario.GazeboSimulator):
Condensed preview — 245 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,345K chars).
[
  {
    "path": ".clang-format",
    "chars": 3112,
    "preview": "---\nLanguage:        Cpp\n# BasedOnStyle:  WebKit\nAccessModifierOffset: -4\nAlignAfterOpenBracket: Align\nAlignConsecutiveA"
  },
  {
    "path": ".docker/Dockerfile",
    "chars": 487,
    "preview": "ARG from=diegoferigo/gym-ignition:pypi-master\nFROM ${from}\n\n# Install the PyPI package in a virtualenv\nARG pip_options=\""
  },
  {
    "path": ".docker/base.Dockerfile",
    "chars": 1826,
    "preview": "ARG from=ubuntu:focal\nFROM ${from}\n\nSHELL [\"/bin/bash\", \"-c\"]\n\n# Setup locales and timezone\nARG TZ=Europe/Rome\nARG DEBIA"
  },
  {
    "path": ".docker/cicd-devel.Dockerfile",
    "chars": 1649,
    "preview": "ARG from=diegoferigo/gym-ignition:base\nFROM ${from}\n\nRUN pip3 install vcstool colcon-common-extensions &&\\\n    rm -r $HO"
  },
  {
    "path": ".docker/cicd-master.Dockerfile",
    "chars": 667,
    "preview": "ARG from=diegoferigo/gym-ignition:base\nFROM ${from}\n\n# Install ignition gazebo\nARG ignition_codename=\"fortress\"\nRUN echo"
  },
  {
    "path": ".docker/docker-compose.yml",
    "chars": 1633,
    "preview": "version: '3.0'\n\nservices:\n\n  base:\n    build:\n      args:\n        from: ubuntu:focal\n      context: .\n      dockerfile: "
  },
  {
    "path": ".docker/entrypoint.sh",
    "chars": 227,
    "preview": "#!/bin/bash\nset -e\n\nif [ ! -x \"/setup_virtualenv.sh\" ] ; then\n    echo \"File '/setup_virtualenv.sh' not found.\"\n    exit"
  },
  {
    "path": ".docker/setup_virtualenv.sh",
    "chars": 412,
    "preview": "#!/bin/bash\nset -eu\n\n# Read the env variable if exists, otherwise fall back to python3\nPYTHON_EXE=python${PYTHON_VERSION"
  },
  {
    "path": ".github/CODEOWNERS",
    "chars": 38,
    "preview": "# Default owners\n*       @diegoferigo\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 1695,
    "preview": "---\nname: Bug report\nabout: Report a bug\nlabels: issue::type::bug\n---\n\n<!-- Remove this warning before posting the issue"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 682,
    "preview": "---\nname: Feature request\nabout: Request a new feature\nlabels: issue::type::enhancement\n---\n\n<!-- Remove this warning be"
  },
  {
    "path": ".github/release.yml",
    "chars": 513,
    "preview": "changelog:\n  exclude:\n    labels:\n      - pr::changelog::ignore\n    authors: [ ]\n  categories:\n    - title: Bug fixing a"
  },
  {
    "path": ".github/workflows/cicd.yml",
    "chars": 18352,
    "preview": "name: CI/CD\n\non:\n  push:\n    branches: [\"**\"]\n    tags-ignore: [\"**\"]\n  pull_request:\n  workflow_dispatch:\n  release:\n  "
  },
  {
    "path": ".github/workflows/docker.yml",
    "chars": 1934,
    "preview": "name: Docker Images\n\non:\n  push:\n    paths:\n      - \".docker/*\"\n      - \".github/workflows/docker.yml\"\n    branches: [\"*"
  },
  {
    "path": ".github/workflows/style.yml",
    "chars": 1481,
    "preview": "name: Code Style\n\non:\n  push:\n    branches: [\"**\"]\n    tags-ignore: [\"**\"]\n  pull_request:\n  workflow_dispatch:\n\njobs:\n\n"
  },
  {
    "path": ".gitignore",
    "chars": 156,
    "preview": "*.mexa64\n*.mexmaci64\n*.autosave\n*.original\n*~\n.DS_Store\nbuild*\n*.bak\n*.old\nCMakeLists.txt.*\nCopy_of_*\n__pycache__\n*.egg-"
  },
  {
    "path": "CMakeLists.txt",
    "chars": 699,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "LICENSE",
    "chars": 7652,
    "preview": "                   GNU LESSER GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007"
  },
  {
    "path": "README.md",
    "chars": 5582,
    "preview": "<p align=\"center\">\n<h1 align=\"center\">gym-ignition</h1>\n</p>\n\n<div align=\"center\">\n<table>\n    <tbody>\n         <tr>\n   "
  },
  {
    "path": "docs/CMakeLists.txt",
    "chars": 416,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "docs/doxygen/CMakeLists.txt",
    "chars": 746,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "docs/sphinx/CMakeLists.txt",
    "chars": 3526,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "docs/sphinx/_templates/module.rst_t",
    "chars": 195,
    "preview": "{%- if show_headings %}\n{{- [basename, \"module\"] | join(' ') | e | heading }}\n\n{% endif -%}\n.. automodule:: {{ qualname "
  },
  {
    "path": "docs/sphinx/_templates/package.rst_t",
    "chars": 1013,
    "preview": "{%- macro automodule(modname, options) -%}\n.. automodule:: {{ modname }}\n{%- for option in options %}\n   :{{ option }}:\n"
  },
  {
    "path": "docs/sphinx/_templates/toc.rst_t",
    "chars": 127,
    "preview": "{{ header | heading }}\n\n.. toctree::\n   :maxdepth: {{ maxdepth }}\n{% for docname in docnames %}\n   {{ docname }}\n{%- end"
  },
  {
    "path": "docs/sphinx/_templates/versioning.html",
    "chars": 453,
    "preview": "{% if versions %}\n<nav id=\"bd-docs-nav\" class=\"bd-links\" aria-label=\"Versions navigation\">\n  <div class=\"bd-toc-item act"
  },
  {
    "path": "docs/sphinx/_templates/versions.html",
    "chars": 805,
    "preview": "{%- if current_version %}\n<div class=\"rst-versions\" data-toggle=\"rst-versions\" role=\"note\" aria-label=\"versions\">\n  <spa"
  },
  {
    "path": "docs/sphinx/apidoc/gym-ignition/gym_ignition.base.rst",
    "chars": 423,
    "preview": "gym\\_ignition.base\n==================\n\n.. automodule:: gym_ignition.base\n   :members:\n   :undoc-members:\n   :show-inheri"
  },
  {
    "path": "docs/sphinx/apidoc/gym-ignition/gym_ignition.context.gazebo.rst",
    "chars": 531,
    "preview": "gym\\_ignition.context.gazebo\n============================\n\n.. automodule:: gym_ignition.context.gazebo\n   :members:\n   :"
  },
  {
    "path": "docs/sphinx/apidoc/gym-ignition/gym_ignition.context.rst",
    "chars": 199,
    "preview": "gym\\_ignition.context\n=====================\n\n.. automodule:: gym_ignition.context\n   :members:\n   :undoc-members:\n   :sh"
  },
  {
    "path": "docs/sphinx/apidoc/gym-ignition/gym_ignition.randomizers.model.rst",
    "chars": 346,
    "preview": "gym\\_ignition.randomizers.model\n===============================\n\n.. automodule:: gym_ignition.randomizers.model\n   :memb"
  },
  {
    "path": "docs/sphinx/apidoc/gym-ignition/gym_ignition.randomizers.physics.rst",
    "chars": 361,
    "preview": "gym\\_ignition.randomizers.physics\n=================================\n\n.. automodule:: gym_ignition.randomizers.physics\n  "
  },
  {
    "path": "docs/sphinx/apidoc/gym-ignition/gym_ignition.randomizers.rst",
    "chars": 631,
    "preview": "gym\\_ignition.randomizers\n=========================\n\n.. automodule:: gym_ignition.randomizers\n   :members:\n   :undoc-mem"
  },
  {
    "path": "docs/sphinx/apidoc/gym-ignition/gym_ignition.rbd.idyntree.rst",
    "chars": 932,
    "preview": "gym\\_ignition.rbd.idyntree\n==========================\n\n.. automodule:: gym_ignition.rbd.idyntree\n   :members:\n   :undoc-"
  },
  {
    "path": "docs/sphinx/apidoc/gym-ignition/gym_ignition.rbd.rst",
    "chars": 490,
    "preview": "gym\\_ignition.rbd\n=================\n\n.. automodule:: gym_ignition.rbd\n   :members:\n   :undoc-members:\n   :show-inheritan"
  },
  {
    "path": "docs/sphinx/apidoc/gym-ignition/gym_ignition.rst",
    "chars": 309,
    "preview": "gym\\_ignition\n=============\n\n.. automodule:: gym_ignition\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\n\n.. toc"
  },
  {
    "path": "docs/sphinx/apidoc/gym-ignition/gym_ignition.runtimes.rst",
    "chars": 520,
    "preview": "gym\\_ignition.runtimes\n======================\n\n.. automodule:: gym_ignition.runtimes\n   :members:\n   :undoc-members:\n   "
  },
  {
    "path": "docs/sphinx/apidoc/gym-ignition/gym_ignition.scenario.rst",
    "chars": 516,
    "preview": "gym\\_ignition.scenario\n======================\n\n.. automodule:: gym_ignition.scenario\n   :members:\n   :undoc-members:\n   "
  },
  {
    "path": "docs/sphinx/apidoc/gym-ignition/gym_ignition.utils.rst",
    "chars": 1066,
    "preview": "gym\\_ignition.utils\n===================\n\n.. automodule:: gym_ignition.utils\n   :members:\n   :undoc-members:\n   :show-inh"
  },
  {
    "path": "docs/sphinx/apidoc/gym-ignition-environments/gym_ignition_environments.models.rst",
    "chars": 962,
    "preview": "gym\\_ignition\\_environments.models\n==================================\n\n.. automodule:: gym_ignition_environments.models\n"
  },
  {
    "path": "docs/sphinx/apidoc/gym-ignition-environments/gym_ignition_environments.randomizers.rst",
    "chars": 652,
    "preview": "gym\\_ignition\\_environments.randomizers\n=======================================\n\n.. automodule:: gym_ignition_environmen"
  },
  {
    "path": "docs/sphinx/apidoc/gym-ignition-environments/gym_ignition_environments.rst",
    "chars": 297,
    "preview": "gym\\_ignition\\_environments\n===========================\n\n.. automodule:: gym_ignition_environments\n   :members:\n   :undo"
  },
  {
    "path": "docs/sphinx/apidoc/gym-ignition-environments/gym_ignition_environments.tasks.rst",
    "chars": 1183,
    "preview": "gym\\_ignition\\_environments.tasks\n=================================\n\n.. automodule:: gym_ignition_environments.tasks\n   "
  },
  {
    "path": "docs/sphinx/apidoc/scenario/scenario.bindings.rst",
    "chars": 414,
    "preview": "scenario.bindings\n=================\n\n.. automodule:: scenario.bindings\n   :members:\n   :undoc-members:\n   :show-inherita"
  },
  {
    "path": "docs/sphinx/apidoc/scenario/scenario.rst",
    "chars": 151,
    "preview": "scenario\n========\n\n.. automodule:: scenario\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\n\n.. toctree::\n   :max"
  },
  {
    "path": "docs/sphinx/breathe/core.rst",
    "chars": 103,
    "preview": ".. _scenario_core:\n\nCore\n====\n\n.. doxygennamespace:: scenario::core\n   :project: scenario\n   :members:\n"
  },
  {
    "path": "docs/sphinx/breathe/gazebo.rst",
    "chars": 111,
    "preview": ".. _scenario_gazebo:\n\nGazebo\n======\n\n.. doxygennamespace:: scenario::gazebo\n   :project: scenario\n   :members:\n"
  },
  {
    "path": "docs/sphinx/conf.py",
    "chars": 4248,
    "preview": "# Configuration file for the Sphinx documentation builder.\n#\n# This file only contains a selection of the most common op"
  },
  {
    "path": "docs/sphinx/getting_started/gym-ignition.rst",
    "chars": 3752,
    "preview": ".. _getting_started_gym_ignition:\n\ngym-ignition\n************\n\nThe previous sections reported the usage of ScenarIO to pe"
  },
  {
    "path": "docs/sphinx/getting_started/manipulation.rst",
    "chars": 16261,
    "preview": ".. _getting_started_manipulation:\n\nManipulation example\n********************\n\nThis example provides a wider overview of "
  },
  {
    "path": "docs/sphinx/getting_started/scenario.rst",
    "chars": 5085,
    "preview": ".. _getting_started_scenario:\n\nScenarIO\n========\n\nIn this getting started section we show how to use the Gazebo ScenarIO"
  },
  {
    "path": "docs/sphinx/index.html",
    "chars": 288,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Redirecting to master branch</title>\n    <meta charset=\"utf-8\">\n    <meta htt"
  },
  {
    "path": "docs/sphinx/index.rst",
    "chars": 2652,
    "preview": ".. _scenario_and_gym_ignition:\n\nScenarIO and gym-ignition\n=========================\n\nThis project targets both *control*"
  },
  {
    "path": "docs/sphinx/info/faq.rst",
    "chars": 4552,
    "preview": "FAQ\n===\n\n.. _faq_citation:\n\nHow to give credit?\n-------------------\n\nIf you use **ScenarIO** or **gym-ignition** for you"
  },
  {
    "path": "docs/sphinx/info/limitations.rst",
    "chars": 1735,
    "preview": "Limitations\n===========\n\nSensors support\n---------------\n\nIgnition Gazebo supports a wide variety of `sensors <https://i"
  },
  {
    "path": "docs/sphinx/installation/developer.rst",
    "chars": 3401,
    "preview": ".. _installation_developer:\n\nDeveloper Installation\n======================\n\nThis installation type is intended for those"
  },
  {
    "path": "docs/sphinx/installation/nightly.rst",
    "chars": 1014,
    "preview": ".. _installation_nightly:\n\nNightly\n=======\n\nThe nightly channel contains the most recent updates of the project.\nAs desc"
  },
  {
    "path": "docs/sphinx/installation/stable.rst",
    "chars": 876,
    "preview": ".. _installation_stable:\n\nStable\n======\n\nThe stable channel is the easiest way to setup your system.\nAs described in the"
  },
  {
    "path": "docs/sphinx/installation/support_policy.rst",
    "chars": 2192,
    "preview": ".. _support_policy:\n\nSupport policy\n==============\n\n**gym-ignition** is an hybrid C++ and Python project and it requires"
  },
  {
    "path": "docs/sphinx/installation/system_configuration.rst",
    "chars": 922,
    "preview": "System Configuration\n********************\n\nThis section applies only to the installations that require building Ignition"
  },
  {
    "path": "docs/sphinx/installation/virtual_environment.rst",
    "chars": 523,
    "preview": "Virtual Environment (optional)\n******************************\n\nThis step is optional but highly recommended.\nVisit the `"
  },
  {
    "path": "docs/sphinx/what/what_is_gym_ignition.rst",
    "chars": 1386,
    "preview": ".. _what_is_gym_ignition:\n\nWhat is gym-ignition?\n=====================\n\n**gym-ignition** is a framework to create **repr"
  },
  {
    "path": "docs/sphinx/what/what_is_scenario.rst",
    "chars": 1498,
    "preview": ".. _what_is_scenario:\n\nWhat is ScenarIO\n================\n\n**ScenarIO** is a C++ abstraction layer to interact with simul"
  },
  {
    "path": "docs/sphinx/why/motivations.rst",
    "chars": 630,
    "preview": ".. _motivations:\n\nIntro\n=====\n\nIn this section we recap the motivations behind this project.\nChoosing the right framewor"
  },
  {
    "path": "docs/sphinx/why/why_gym_ignition.rst",
    "chars": 2897,
    "preview": ".. _why_gym_ignition:\n\nWhy gym-ignition\n================\n\nIn the previous sections we described why we developed ScenarI"
  },
  {
    "path": "docs/sphinx/why/why_ignition_gazebo.rst",
    "chars": 4626,
    "preview": ".. _why_ignition_gazebo:\n\nWhy Ignition Gazebo\n===================\n\nIn this section we want to go a bit deeper in the mot"
  },
  {
    "path": "docs/sphinx/why/why_scenario.rst",
    "chars": 2344,
    "preview": ".. _why_scenario:\n\nWhy ScenarIO\n============\n\n*SCENe interfAces for Robot Input/Output* is an abstraction layer to inter"
  },
  {
    "path": "examples/panda_pick_and_place.py",
    "chars": 13201,
    "preview": "import enum\nimport time\nfrom functools import partial\nfrom typing import List\n\nimport gym_ignition\nimport gym_ignition_e"
  },
  {
    "path": "examples/python/launch_cartpole.py",
    "chars": 2104,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "pyproject.toml",
    "chars": 303,
    "preview": "[build-system]\nbuild-backend = \"setuptools.build_meta\"\nrequires = [\n    \"wheel\",\n    \"setuptools>=45\",\n    \"setuptools_s"
  },
  {
    "path": "python/gym_ignition/__init__.py",
    "chars": 1250,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/base/__init__.py",
    "chars": 263,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/base/runtime.py",
    "chars": 2865,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/base/task.py",
    "chars": 7298,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/context/__init__.py",
    "chars": 237,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/context/gazebo/__init__.py",
    "chars": 250,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/context/gazebo/controllers.py",
    "chars": 1478,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/context/gazebo/plugin.py",
    "chars": 2320,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/randomizers/__init__.py",
    "chars": 273,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/randomizers/abc.py",
    "chars": 3774,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/randomizers/gazebo_env_randomizer.py",
    "chars": 4994,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/randomizers/model/__init__.py",
    "chars": 234,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/randomizers/model/sdf.py",
    "chars": 11116,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/randomizers/physics/__init__.py",
    "chars": 235,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/randomizers/physics/dart.py",
    "chars": 771,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/rbd/__init__.py",
    "chars": 259,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/rbd/conversions.py",
    "chars": 2547,
    "preview": "import abc\nfrom typing import Tuple\n\nimport numpy as np\nfrom scipy.spatial.transform import Rotation\n\n\nclass Transform(a"
  },
  {
    "path": "python/gym_ignition/rbd/idyntree/__init__.py",
    "chars": 289,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/rbd/idyntree/helpers.py",
    "chars": 2964,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/rbd/idyntree/inverse_kinematics_nlp.py",
    "chars": 22415,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/rbd/idyntree/kindyncomputations.py",
    "chars": 14936,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/rbd/idyntree/numpy.py",
    "chars": 3737,
    "preview": "import abc\nfrom typing import Tuple, Union\n\nimport idyntree.bindings as idt\nimport numpy as np\nfrom gym_ignition import "
  },
  {
    "path": "python/gym_ignition/rbd/utils.py",
    "chars": 2220,
    "preview": "# Copyright (C) 2021 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/runtimes/__init__.py",
    "chars": 263,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/runtimes/gazebo_runtime.py",
    "chars": 8538,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/runtimes/realtime_runtime.py",
    "chars": 2310,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/scenario/__init__.py",
    "chars": 261,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/scenario/model_with_file.py",
    "chars": 402,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/scenario/model_wrapper.py",
    "chars": 549,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/utils/__init__.py",
    "chars": 298,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/utils/logger.py",
    "chars": 2437,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/utils/math.py",
    "chars": 1519,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/utils/misc.py",
    "chars": 394,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/utils/resource_finder.py",
    "chars": 2486,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/utils/scenario.py",
    "chars": 3509,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition/utils/typing.py",
    "chars": 736,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition_environments/__init__.py",
    "chars": 1753,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition_environments/models/__init__.py",
    "chars": 262,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition_environments/models/cartpole.py",
    "chars": 1510,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition_environments/models/icub.py",
    "chars": 3991,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition_environments/models/panda.py",
    "chars": 2933,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition_environments/models/pendulum.py",
    "chars": 1510,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition_environments/randomizers/__init__.py",
    "chars": 257,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition_environments/randomizers/cartpole.py",
    "chars": 6117,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition_environments/randomizers/cartpole_no_rand.py",
    "chars": 2502,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition_environments/tasks/__init__.py",
    "chars": 357,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition_environments/tasks/cartpole_continuous_balancing.py",
    "chars": 4643,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition_environments/tasks/cartpole_continuous_swingup.py",
    "chars": 4883,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition_environments/tasks/cartpole_discrete_balancing.py",
    "chars": 4628,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "python/gym_ignition_environments/tasks/pendulum_swingup.py",
    "chars": 3941,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "scenario/CMakeLists.txt",
    "chars": 6968,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "scenario/README.md",
    "chars": 5509,
    "preview": "# ScenarIO\n\n[![C++ standard](https://img.shields.io/badge/standard-C++17-blue.svg?style=flat&logo=c%2B%2B)](https://isoc"
  },
  {
    "path": "scenario/bindings/CMakeLists.txt",
    "chars": 2608,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "scenario/bindings/__init__.py",
    "chars": 7139,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "scenario/bindings/core/CMakeLists.txt",
    "chars": 1917,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "scenario/bindings/core/core.i",
    "chars": 3052,
    "preview": "%module(package=\"scenario.bindings\") core\n\n%{\n#define SWIG_FILE_WITH_INIT\n#include \"scenario/core/Joint.h\"\n#include \"sce"
  },
  {
    "path": "scenario/bindings/gazebo/CMakeLists.txt",
    "chars": 1990,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "scenario/bindings/gazebo/gazebo.i",
    "chars": 3168,
    "preview": "%module(package=\"scenario.bindings\") gazebo\n\n%{\n#define SWIG_FILE_WITH_INIT\n#include \"scenario/gazebo/GazeboEntity.h\"\n#i"
  },
  {
    "path": "scenario/bindings/gazebo/to_gazebo.i",
    "chars": 1068,
    "preview": "%pythonbegin %{\nfrom typing import Union\n%}\n\n%extend scenario::core::World {\n  %pythoncode %{\n    def to_gazebo(self) ->"
  },
  {
    "path": "scenario/cmake/AddUninstallTarget.cmake",
    "chars": 3780,
    "preview": "#.rst:\n# AddUninstallTarget\n# ------------------\n#\n# Add the \"uninstall\" target for your project::\n#\n#   include(AddUnin"
  },
  {
    "path": "scenario/cmake/AliasImportedTarget.cmake",
    "chars": 3405,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "scenario/cmake/FindIgnitionDistribution.cmake",
    "chars": 2862,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "scenario/cmake/FindPackageHandleStandardArgs.cmake",
    "chars": 22946,
    "preview": "# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying\n# file Copyright.txt or https://cmake.org/l"
  },
  {
    "path": "scenario/cmake/FindPackageMessage.cmake",
    "chars": 1711,
    "preview": "# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying\n# file Copyright.txt or https://cmake.org/l"
  },
  {
    "path": "scenario/cmake/FindPython/Support.cmake",
    "chars": 161302,
    "preview": "# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying\n# file Copyright.txt or https://cmake.org/l"
  },
  {
    "path": "scenario/cmake/FindPython3.cmake",
    "chars": 16478,
    "preview": "# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying\n# file Copyright.txt or https://cmake.org/l"
  },
  {
    "path": "scenario/cmake/FindSphinx.cmake",
    "chars": 654,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "scenario/cmake/FindSphinxApidoc.cmake",
    "chars": 678,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "scenario/cmake/FindSphinxMultiVersion.cmake",
    "chars": 720,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "scenario/cmake/ImportTargetsCitadel.cmake",
    "chars": 1926,
    "preview": "include(AliasImportedTarget)\n\n# https://ignitionrobotics.org/docs/citadel/install#citadel-libraries\n\nalias_imported_targ"
  },
  {
    "path": "scenario/cmake/ImportTargetsDome.cmake",
    "chars": 2204,
    "preview": "include(AliasImportedTarget)\n\n# https://ignitionrobotics.org/docs/dome/install#dome-libraries\n\nalias_imported_target(\n  "
  },
  {
    "path": "scenario/cmake/ImportTargetsEdifice.cmake",
    "chars": 1929,
    "preview": "include(AliasImportedTarget)\n\n# https://ignitionrobotics.org/docs/edifice/install#edifice-libraries\n\nalias_imported_targ"
  },
  {
    "path": "scenario/cmake/ImportTargetsFortress.cmake",
    "chars": 1931,
    "preview": "include(AliasImportedTarget)\n\n# https://ignitionrobotics.org/docs/fortress/install#fortress-libraries\n\nalias_imported_ta"
  },
  {
    "path": "scenario/deps/CMakeLists.txt",
    "chars": 3366,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "scenario/deps/clara/clara.hpp",
    "chars": 43451,
    "preview": "// Copyright 2017 Two Blue Cubes Ltd. All rights reserved.\n//\n// Distributed under the Boost Software License, Version 1"
  },
  {
    "path": "scenario/pyproject.toml",
    "chars": 467,
    "preview": "# Copyright (C) 2021 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "scenario/setup.cfg",
    "chars": 1782,
    "preview": "# Copyright (C) 2021 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "scenario/setup.py",
    "chars": 867,
    "preview": "# Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "scenario/src/CMakeLists.txt",
    "chars": 1115,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "scenario/src/controllers/CMakeLists.txt",
    "chars": 2848,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "scenario/src/controllers/include/scenario/controllers/ComputedTorqueFixedBase.h",
    "chars": 1824,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This software may be modifi"
  },
  {
    "path": "scenario/src/controllers/include/scenario/controllers/Controller.h",
    "chars": 2056,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This software may be modifi"
  },
  {
    "path": "scenario/src/controllers/include/scenario/controllers/References.h",
    "chars": 1512,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This software may be modifi"
  },
  {
    "path": "scenario/src/controllers/src/ComputedTorqueFixedBase.cpp",
    "chars": 10911,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This software may be modifi"
  },
  {
    "path": "scenario/src/core/CMakeLists.txt",
    "chars": 2950,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT). All rights reserved.\n# This software may be modified and dis"
  },
  {
    "path": "scenario/src/core/include/scenario/core/Joint.h",
    "chars": 18064,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This software may be modifi"
  },
  {
    "path": "scenario/src/core/include/scenario/core/Link.h",
    "chars": 6316,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This software may be modifi"
  },
  {
    "path": "scenario/src/core/include/scenario/core/Model.h",
    "chars": 20376,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This software may be modifi"
  },
  {
    "path": "scenario/src/core/include/scenario/core/World.h",
    "chars": 2154,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This software may be modifi"
  },
  {
    "path": "scenario/src/core/include/scenario/core/utils/Log.h",
    "chars": 704,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This software may be modifi"
  },
  {
    "path": "scenario/src/core/include/scenario/core/utils/signals.h",
    "chars": 996,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This software may be modifi"
  },
  {
    "path": "scenario/src/core/include/scenario/core/utils/utils.h",
    "chars": 753,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This software may be modifi"
  },
  {
    "path": "scenario/src/core/src/signals.cpp",
    "chars": 2524,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This software may be modifi"
  },
  {
    "path": "scenario/src/core/src/utils.cpp",
    "chars": 592,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This software may be modifi"
  },
  {
    "path": "scenario/src/gazebo/CMakeLists.txt",
    "chars": 6203,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n# All rights reserved.\n#\n#  This project is dual licensed und"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/GazeboEntity.h",
    "chars": 3745,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/GazeboSimulator.h",
    "chars": 5889,
    "preview": "/*\n * Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/Joint.h",
    "chars": 8910,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/Link.h",
    "chars": 6383,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/Log.h",
    "chars": 1598,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/Model.h",
    "chars": 11941,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/World.h",
    "chars": 7380,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/components/BasePoseTarget.h",
    "chars": 1951,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/components/BaseWorldAccelerationTarget.h",
    "chars": 2671,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/components/BaseWorldVelocityTarget.h",
    "chars": 2619,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/components/ExternalWorldWrenchCmdWithDuration.h",
    "chars": 2712,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/components/HistoryOfAppliedJointForces.h",
    "chars": 2287,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/components/JointAcceleration.h",
    "chars": 2335,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/components/JointAccelerationTarget.h",
    "chars": 2379,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/components/JointControlMode.h",
    "chars": 2090,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/components/JointController.h",
    "chars": 1890,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/components/JointControllerPeriod.h",
    "chars": 2063,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/components/JointPID.h",
    "chars": 1867,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/components/JointPositionTarget.h",
    "chars": 2172,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/components/JointVelocityTarget.h",
    "chars": 2343,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/components/SimulatedTime.h",
    "chars": 2012,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/components/Timestamp.h",
    "chars": 1937,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/exceptions.h",
    "chars": 7610,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/helpers.h",
    "chars": 16269,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/include/scenario/gazebo/utils.h",
    "chars": 9360,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/src/GazeboSimulator.cpp",
    "chars": 26555,
    "preview": "/*\n * Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/src/Joint.cpp",
    "chars": 39346,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/src/Link.cpp",
    "chars": 19987,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/src/Model.cpp",
    "chars": 41112,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/src/World.cpp",
    "chars": 15648,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/src/helpers.cpp",
    "chars": 19313,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/gazebo/src/utils.cpp",
    "chars": 12866,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  },
  {
    "path": "scenario/src/plugins/CMakeLists.txt",
    "chars": 1090,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n# All rights reserved.\n#\n#  This project is dual licensed und"
  },
  {
    "path": "scenario/src/plugins/ControllerRunner/CMakeLists.txt",
    "chars": 2271,
    "preview": "# Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n# All rights reserved.\n#\n#  This project is dual licensed und"
  },
  {
    "path": "scenario/src/plugins/ControllerRunner/ControllerRunner.cpp",
    "chars": 13263,
    "preview": "/*\n * Copyright (C) 2020 Istituto Italiano di Tecnologia (IIT)\n * All rights reserved.\n *\n * This project is dual licens"
  }
]

// ... and 45 more files (download for full content)

About this extraction

This page contains the full source code of the robotology/gym-ignition GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 245 files (1.2 MB), approximately 314.1k tokens, and a symbol index with 679 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!