opty 1.5.0
Tool for optimizing dynamic systems using direct collocation.
License: BSD-2-clause

.. list-table::

   * - PyPi
     - .. image:: https://img.shields.io/pypi/v/opty.svg
          :target: https://pypi.org/project/opty
       .. image:: https://pepy.tech/badge/opty
          :target: https://pypi.org/project/opty
   * - Anaconda
     - .. image:: https://anaconda.org/conda-forge/opty/badges/version.svg
          :target: https://anaconda.org/conda-forge/opty
       .. image:: https://anaconda.org/conda-forge/opty/badges/downloads.svg
          :target: https://anaconda.org/conda-forge/opty
   * - Documentation
     - .. image:: https://readthedocs.org/projects/opty/badge/?version=stable
          :target: http://opty.readthedocs.io
   * - JOSS Paper
     - .. image:: http://joss.theoj.org/papers/10.21105/joss.00300/status.svg
          :target: https://doi.org/10.21105/joss.00300
   * - Zenodo Archive
     - .. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.1162870.svg
          :target: https://doi.org/10.5281/zenodo.1162870
   * - Continous Integration
     - .. image:: https://github.com/csu-hmc/opty/actions/workflows/tests.yml/badge.svg

Introduction
============

``opty`` utilizes symbolic descriptions of differential algebraic equations
expressed with SymPy_ to form the constraints needed to solve optimal control
and parameter identification problems using the direct collocation method and
`nonlinear programming`_ (NLP). In general, if one can express the continuous
first order differential algebraic equations of the system as symbolic
expressions, ``opty`` will automatically generate a function to efficiently
evaluate the dynamical constraints and a function that evaluates the sparse
Jacobian of the constraints, which have been optimized for speed and memory
consumption. The translation of the dynamical system description to the NLP
form, primarily the formation of the constraints and the Jacobian of the
constraints, manually is a time consuming and error prone process. ``opty``
eliminates both of those issues.

opty uses its primary dependencies in the following ways:

- SymPy: Symbolically discretizes the DAEs, analytically computes all necessary
  derivatives, and generates C code to efficiently evaluate the DAEs and their
  associated derivatives.
- Cython + NumPy: Just-In-Time compiles the C code generated by SymPy and
  wraps it for use with NumPy arrays.
- cyipopt: Wraps the Ipopt C API and provides a generic NLP problem definition
  class which opty's problem class is derived from to facilitate input and
  output from Ipopt as NumPy arrays.
- Ipopt: Consumes the numerical problem definition passed via cyipopt and then
  solves it using an interior point method.

.. _SymPy: http://www.sympy.org
.. _nonlinear programming: https://en.wikipedia.org/wiki/Nonlinear_programming

Features
--------

- Both implicit and explicit forms of the first order ordinary differential
  equations and differential algebraic equations are supported, i.e. there is
  no need to solve for the derivatives of the dependent variables.
- Backward Euler or Midpoint integration methods.
- Supports both trajectory optimization and parameter identification,
  independently or simultaneously.
- Solve fixed duration or variable duration problems.
- Easy specification of bounds on free variables.
- Easily specify additional "instance" constraints.
- Supports additional equality and inequality path constraints.
- Variables the in the differential equations can be specified by numerical
  functions to augment the symbolics.
- Efficient numerical execution of large equations of motion.
- Automatic parallel execution using openmp if installed.
- Built with support of sympy.physics.mechanics and PyDy in mind.
- Low performance pure Python mode that obviates the need for just-in-time C
  compilation.

Example Solutions
-----------------

Animations from some of the `examples
<https://opty.readthedocs.io/stable/examples/index.html>`_.

.. list-table::
   :align: center

   * - .. image:: https://opty.readthedocs.io/latest/_images/sphx_glr_plot_one_legged_time_trial_thumb.gif
          :width: 200px
     - .. image:: https://opty.readthedocs.io/latest/_images/sphx_glr_plot_ball_rolling_on_spinning_disc_thumb.gif
          :width: 200px
     - .. image:: https://opty.readthedocs.io/latest/_images/sphx_glr_plot_sit_to_stand_thumb.gif
          :width: 200px
   * - .. image:: https://opty.readthedocs.io/latest/_images/sphx_glr_plot_particle_in_tube_thumb.gif
          :width: 200px
     - .. image:: https://opty.readthedocs.io/latest/_images/sphx_glr_plot_human_gait_thumb.gif
          :width: 200px
     - .. image:: https://opty.readthedocs.io/latest/_images/sphx_glr_plot_park2004_thumb.gif
          :width: 200px

Installation
============

The required dependencies are as follows:

- cyipopt >= 1.1.0 [with ipopt >= 3.11 (Linux & OSX), >= 3.13 (Windows)]
- cython >= 0.29.28 [with a `C compiler`_]
- numpy >= 1.21.5
- python 3.9-3.14
- setuptools >= 59.6.0
- sympy >= 1.9.1

.. _C compiler: https://cython.readthedocs.io/en/stable/src/quickstart/install.html

The optional dependencies are as follows:

- matplotlib >= 3.5.1
- openmp
- scipy >= 1.8.0

To run all of the examples the following additional dependencies may be needed:

- gait2d
- pandas >= 1.3.5
- pydy >= 0.6.0
- pytables >= 3.7.0
- pyyaml >= 5.4.1
- symmeplot
- yeadon >= 1.4.0

The easiest way to install opty is to first install Anaconda_ (or Miniconda_ or
Miniforge_) and use the conda package manager to install opty and any desired
optional dependencies from the Conda Forge channel, e.g. opty::

   $ conda install --channel conda-forge opty

and the optional dependencies::

   $ conda install --channel conda-forge matplotlib openmp scipy

.. _Anaconda: https://www.continuum.io/downloads
.. _Miniconda: https://conda.io/miniconda.html
.. _Miniforge: https://conda-forge.org/miniforge/

Opty can be installed with pip, but this will require installing and compiling
cyipopt if it is not already installed::

   $ pip install opty

See the `cyipopt documentation`_ for information on installing that package.

.. _cyipopt documentation: https://cyipopt.readthedocs.io

There are also several dependency groups::

   $ pip install opty[optional]  # use extra functionality in opty
   $ pip install opty[examples]  # run all example scripts
   $ pip install opty[doc]  # build the documentation

Custom Ipopt
------------

If you want a custom installation of any of the dependencies, e.g. Ipopt, you
must first install Ipopt along with it's headers. For example, on Debian based
systems you can use the package manager::

   $ sudo apt-get install coinor-libipopt1v5 coinor-libipopt-dev

or prebuilt binaries can be downloaded from
https://www.coin-or.org/download/binary/Ipopt/.

For customized installation (usually desired for performance) follow the
instructions on the Ipopt documentation to compile the library. If you install
to a location other than ``/usr/local`` on Unix systems you will likely have to
set the ``LD_LIBRARY_PATH`` so that you can link to Ipopt when installing
``cyipopt``.

Once Ipopt is installed and accessible, install conda then create an environment::

   $ conda create -n opty-custom -c conda-forge cython numpy pip setuptools sympy
   $ source activate opty-custom
   (opty-custom)$ pip install cyipopt  # this will compile cyipopt against the available ipopt
   (opty-custom)$ pip install opty

If you want to develop opty, create a conda environment with all of the
development dependencies installed::

   $ cd /path/to/opty/
   $ conda env create -f opty-dev-env.yml
   $ conda activate opty-dev

Next install the development version of opty with::

   (opty-dev)$ python -m pip install --no-deps --no-build-isolation --editable .

Usage
=====

There are several examples available in the ``examples`` directory and the
``examples-gallery/beginner``, ``examples-gallery/intermediate`` and
``examples-gallery/advanced`` directories. The optimal torque to swing up a
pendulum with minimal energy can be run with::

   $ python examples-gallery/beginner/plot_pendulum_swing_up_fixed_duration.py

Failed Compilation
------------------

If compilation fails it may be helpful to manually compile the generated Cython
extension. To do so, provide a destination path to the ``tmp_dir`` kwarg when
you instantiate ``Problem()``, e.g.:

.. code:: python

   p = Problem(..., tmp_dir='opty_source')

You can then compile the files manually by navigating into the ``opty_source``
directory and running::

   $ cd /path/to/opty_source
   $ python ufuncify_matrix_X_setup.py build_ext --inplace

The highest integer value of ``X`` will be the most recently generated set of
source files.

Build Documentation
===================

Build the HTML documentation with::

   (opty-dev)$ cd /path/to/opty/docs
   (opty-dev)$ make html

and open the result with your default web browser, for example::

   $ xdg-open _build/html/index.html

Alternatively, in the windows explorer open
``\path\to\opty\docs\_build\html\index.html``.

Acknowledgements
================

opty was created to generalize and make more accessible the optimal control
methods Prof. Ton van den Bogert and his collaborators developed and use for
investigating control of musculoskeletal models. His pioneering work and help
made the development of opty possible.

Funding
-------

The work was partially funded by the State of Ohio Third Frontier Commission
through the Wright Center for Sensor Systems Engineering (WCSSE), by the USA
National Science Foundation under Grant No. 1344954, and by National Center of
Simulation in Rehabilitation Research 2014 Visiting Scholarship at Stanford
University, and the CZI grant CZIF2021-006198 and grant DOI
https://doi.org/10.37921/240361looxoj from the Chan Zuckerberg Initiative
Foundation (funder DOI 10.13039/100014989).