qpmpc


Nameqpmpc JSON
Version 3.0.1 PyPI version JSON
download
home_pageNone
SummaryLinear time-variant model predictive control in Python.
upload_time2023-12-21 14:34:57
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseNone
keywords model predictive control linear time-varying
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # qpmpc

[![Build](https://img.shields.io/github/actions/workflow/status/stephane-caron/qpmpc/build.yml?branch=main)](https://github.com/stephane-caron/qpmpc/actions)
[![Coverage](https://coveralls.io/repos/github/stephane-caron/qpmpc/badge.svg?branch=main)](https://coveralls.io/github/stephane-caron/qpmpc?branch=main)
[![Documentation](https://img.shields.io/badge/docs-online-brightgreen?logo=read-the-docs&style=flat)](https://scaron.info/doc/qpmpc/)
[![PyPI version](https://img.shields.io/pypi/v/qpmpc)](https://pypi.org/project/qpmpc/0.6.0/)

Model predictive control (MPC) in Python for optimal-control problems that are quadratic programs (QP). This includes linear time-invariant (LTI) and time-variant (LTV) systems with linear constraints. The corresponding QP has the form:

> ![qpmpc](https://raw.githubusercontent.com/stephane-caron/qpmpc/main/doc/src/images/qpmpc.svg)

This module is designed for prototyping. If you need performance, check out the [alternatives](#alternatives) below.

## Installation

```sh
pip install qpmpc
```

## Usage

This module defines a one-stop shop function:

```python
solve_mpc(problem: MPCProblem, solver: str) -> Plan
```

The [``MPCProblem``](https://scaron.info/doc/qpmpc/usage.html#qpmpc.mpc_problem.MPCProblem) defines the model predictive control problem (LTV system, LTV constraints, initial state and cost function to optimize) while the returned [``Plan``](https://tasts-robots.org/doc/qpmpc/usage.html#qpmpc.plan.Plan) holds the state and input trajectories that result from optimizing the problem (if a solution exists). The ``solver`` string is used to select the backend [quadratic programming solver](https://github.com/stephane-caron/qpsolvers#solvers).

## Example

Let us define a triple integrator:

```python
    import numpy as np

    horizon_duration = 1.0  # [s]
    N = 16  # number of discretization steps
    T = horizon_duration / N
    A = np.array([[1.0, T, T ** 2 / 2.0], [0.0, 1.0, T], [0.0, 0.0, 1.0]])
    B = np.array([T ** 3 / 6.0, T ** 2 / 2.0, T]).reshape((3, 1))
```

Suppose for the sake of example that acceleration is the main constraint acting on our system. We thus define an acceleration constraint ``|acceleration| <= max_accel``:

```python
    max_accel = 3.0  # [m] / [s] / [s]
    accel_from_state = np.array([0.0, 0.0, 1.0])
    C = np.vstack([+accel_from_state, -accel_from_state])
    e = np.array([+max_accel, +max_accel])
```

This leads us to the following linear MPC problem:

```python
    from qpmpc import MPCProblem

    x_init = np.array([0.0, 0.0, 0.0])
    x_goal = np.array([1.0, 0.0, 0.0])
    problem = MPCProblem(
        transition_state_matrix=A,
        transition_input_matrix=B,
        ineq_state_matrix=C,
        ineq_input_matrix=None,
        ineq_vector=e,
        initial_state=x_init,
        goal_state=x_goal,
        nb_timesteps=N,
        terminal_cost_weight=1.0,
        stage_state_cost_weight=None,
        stage_input_cost_weight=1e-6,
    )
```

We can solve it with:

```python
    from qpmpc import solve_mpc

    solution = solve_mpc(problem, solver="proxqp")
```

The solution holds complete state and input trajectories as stacked vectors. For instance, we can plot positions, velocities and accelerations as follows:

```python
    import pylab

    t = np.linspace(0.0, horizon_duration, N + 1)
    X = solution.states
    positions, velocities, accelerations = X[:, 0], X[:, 1], X[:, 2]
    pylab.ion()
    pylab.plot(t, positions)
    pylab.plot(t, velocities)
    pylab.plot(t, accelerations)
    pylab.grid(True)
    pylab.legend(("position", "velocity", "acceleration"))
```

This example produces the following trajectory:

![2022-03-30-172206_1920x1080_scrot](https://user-images.githubusercontent.com/1189580/160871543-3734ec65-fe74-4a6f-8452-a877aa4050b1.png)

The behavior is a weighted compromise between reaching the goal state (weight ``1.0``) and keeping reasonable finite jerk inputs (weight ``1e-6``). The latter mitigate bang-bang accelerations but prevent fully reaching the goal within the horizon. See the [examples](examples/) folder for more examples.

## Areas of improvement

This module is incomplete with regards to the following points:

- Cost functions: can be extended to general linear stage cost functions
- Documentation: there are some undocumented functions
- Test coverage: only one end-to-end test

Check out the [contribution guidelines](CONTRIBUTING.md) if you are interested in lending a hand.

## Alternatives

This module is designed for faster prototyping rather than performance. You can also check out the following open-source libraries:

| Name                                                       | Systems               | Languages  | License      |
|------------------------------------------------------------|-----------------------|------------|--------------|
| [Copra (LTV fork)](https://github.com/ANYbotics/copra)     | Linear time-variant   | Python/C++ | BSD-2-Clause |
| [Copra (original)](https://github.com/jrl-umi3218/copra)   | Linear time-invariant | Python/C++ | BSD-2-Clause |
| [Crocoddyl](https://github.com/loco-3d/crocoddyl)          | Nonlinear             | Python/C++ | BSD-3-Clause |
| [mpc-interface](https://github.com/Gepetto/mpc-interface)  | Linear time-variant   | Python/C++ | BSD-2-Clause |
| [pyMPC](https://github.com/forgi86/pyMPC)                  | Linear time-variant   | Python     | MIT          |

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "qpmpc",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "St\u00e9phane Caron <stephane.caron@normalesup.org>",
    "keywords": "model,predictive,control,linear,time-varying",
    "author": null,
    "author_email": "St\u00e9phane Caron <stephane.caron@normalesup.org>",
    "download_url": "https://files.pythonhosted.org/packages/98/c7/4199bca033e81d4548af37417f9ac40bc925eb93c6ca0383fa83480a868a/qpmpc-3.0.1.tar.gz",
    "platform": null,
    "description": "# qpmpc\n\n[![Build](https://img.shields.io/github/actions/workflow/status/stephane-caron/qpmpc/build.yml?branch=main)](https://github.com/stephane-caron/qpmpc/actions)\n[![Coverage](https://coveralls.io/repos/github/stephane-caron/qpmpc/badge.svg?branch=main)](https://coveralls.io/github/stephane-caron/qpmpc?branch=main)\n[![Documentation](https://img.shields.io/badge/docs-online-brightgreen?logo=read-the-docs&style=flat)](https://scaron.info/doc/qpmpc/)\n[![PyPI version](https://img.shields.io/pypi/v/qpmpc)](https://pypi.org/project/qpmpc/0.6.0/)\n\nModel predictive control (MPC) in Python for optimal-control problems that are quadratic programs (QP). This includes linear time-invariant (LTI) and time-variant (LTV) systems with linear constraints. The corresponding QP has the form:\n\n> ![qpmpc](https://raw.githubusercontent.com/stephane-caron/qpmpc/main/doc/src/images/qpmpc.svg)\n\nThis module is designed for prototyping. If you need performance, check out the [alternatives](#alternatives) below.\n\n## Installation\n\n```sh\npip install qpmpc\n```\n\n## Usage\n\nThis module defines a one-stop shop function:\n\n```python\nsolve_mpc(problem: MPCProblem, solver: str) -> Plan\n```\n\nThe [``MPCProblem``](https://scaron.info/doc/qpmpc/usage.html#qpmpc.mpc_problem.MPCProblem) defines the model predictive control problem (LTV system, LTV constraints, initial state and cost function to optimize) while the returned [``Plan``](https://tasts-robots.org/doc/qpmpc/usage.html#qpmpc.plan.Plan) holds the state and input trajectories that result from optimizing the problem (if a solution exists). The ``solver`` string is used to select the backend [quadratic programming solver](https://github.com/stephane-caron/qpsolvers#solvers).\n\n## Example\n\nLet us define a triple integrator:\n\n```python\n    import numpy as np\n\n    horizon_duration = 1.0  # [s]\n    N = 16  # number of discretization steps\n    T = horizon_duration / N\n    A = np.array([[1.0, T, T ** 2 / 2.0], [0.0, 1.0, T], [0.0, 0.0, 1.0]])\n    B = np.array([T ** 3 / 6.0, T ** 2 / 2.0, T]).reshape((3, 1))\n```\n\nSuppose for the sake of example that acceleration is the main constraint acting on our system. We thus define an acceleration constraint ``|acceleration| <= max_accel``:\n\n```python\n    max_accel = 3.0  # [m] / [s] / [s]\n    accel_from_state = np.array([0.0, 0.0, 1.0])\n    C = np.vstack([+accel_from_state, -accel_from_state])\n    e = np.array([+max_accel, +max_accel])\n```\n\nThis leads us to the following linear MPC problem:\n\n```python\n    from qpmpc import MPCProblem\n\n    x_init = np.array([0.0, 0.0, 0.0])\n    x_goal = np.array([1.0, 0.0, 0.0])\n    problem = MPCProblem(\n        transition_state_matrix=A,\n        transition_input_matrix=B,\n        ineq_state_matrix=C,\n        ineq_input_matrix=None,\n        ineq_vector=e,\n        initial_state=x_init,\n        goal_state=x_goal,\n        nb_timesteps=N,\n        terminal_cost_weight=1.0,\n        stage_state_cost_weight=None,\n        stage_input_cost_weight=1e-6,\n    )\n```\n\nWe can solve it with:\n\n```python\n    from qpmpc import solve_mpc\n\n    solution = solve_mpc(problem, solver=\"proxqp\")\n```\n\nThe solution holds complete state and input trajectories as stacked vectors. For instance, we can plot positions, velocities and accelerations as follows:\n\n```python\n    import pylab\n\n    t = np.linspace(0.0, horizon_duration, N + 1)\n    X = solution.states\n    positions, velocities, accelerations = X[:, 0], X[:, 1], X[:, 2]\n    pylab.ion()\n    pylab.plot(t, positions)\n    pylab.plot(t, velocities)\n    pylab.plot(t, accelerations)\n    pylab.grid(True)\n    pylab.legend((\"position\", \"velocity\", \"acceleration\"))\n```\n\nThis example produces the following trajectory:\n\n![2022-03-30-172206_1920x1080_scrot](https://user-images.githubusercontent.com/1189580/160871543-3734ec65-fe74-4a6f-8452-a877aa4050b1.png)\n\nThe behavior is a weighted compromise between reaching the goal state (weight ``1.0``) and keeping reasonable finite jerk inputs (weight ``1e-6``). The latter mitigate bang-bang accelerations but prevent fully reaching the goal within the horizon. See the [examples](examples/) folder for more examples.\n\n## Areas of improvement\n\nThis module is incomplete with regards to the following points:\n\n- Cost functions: can be extended to general linear stage cost functions\n- Documentation: there are some undocumented functions\n- Test coverage: only one end-to-end test\n\nCheck out the [contribution guidelines](CONTRIBUTING.md) if you are interested in lending a hand.\n\n## Alternatives\n\nThis module is designed for faster prototyping rather than performance. You can also check out the following open-source libraries:\n\n| Name                                                       | Systems               | Languages  | License      |\n|------------------------------------------------------------|-----------------------|------------|--------------|\n| [Copra (LTV fork)](https://github.com/ANYbotics/copra)     | Linear time-variant   | Python/C++ | BSD-2-Clause |\n| [Copra (original)](https://github.com/jrl-umi3218/copra)   | Linear time-invariant | Python/C++ | BSD-2-Clause |\n| [Crocoddyl](https://github.com/loco-3d/crocoddyl)          | Nonlinear             | Python/C++ | BSD-3-Clause |\n| [mpc-interface](https://github.com/Gepetto/mpc-interface)  | Linear time-variant   | Python/C++ | BSD-2-Clause |\n| [pyMPC](https://github.com/forgi86/pyMPC)                  | Linear time-variant   | Python     | MIT          |\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Linear time-variant model predictive control in Python.",
    "version": "3.0.1",
    "project_urls": {
        "Changelog": "https://github.com/stephane-caron/qpmpc/blob/main/CHANGELOG.md",
        "Documentation": "https://scaron.info/doc/qpmpc/",
        "Source": "https://github.com/stephane-caron/qpmpc",
        "Tracker": "https://github.com/stephane-caron/qpmpc/issues"
    },
    "split_keywords": [
        "model",
        "predictive",
        "control",
        "linear",
        "time-varying"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "a98c45405fea297c567fc9f95cceb2f55668c53a247b7c79f3a3bf24944984ba",
                "md5": "407d42ad7366be6b26d9fbbc3d590ac5",
                "sha256": "044f0952ba95223c1fc3571bd7b013687a439f7a23d0d0c2ace6515b8afa4c80"
            },
            "downloads": -1,
            "filename": "qpmpc-3.0.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "407d42ad7366be6b26d9fbbc3d590ac5",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 20038,
            "upload_time": "2023-12-21T14:34:54",
            "upload_time_iso_8601": "2023-12-21T14:34:54.336624Z",
            "url": "https://files.pythonhosted.org/packages/a9/8c/45405fea297c567fc9f95cceb2f55668c53a247b7c79f3a3bf24944984ba/qpmpc-3.0.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "98c74199bca033e81d4548af37417f9ac40bc925eb93c6ca0383fa83480a868a",
                "md5": "e8c7b7420d518ea08e1c07326f5afadc",
                "sha256": "5394acc4969159c03af946a522b62d510617da090cb755805dc248b4e0ebe567"
            },
            "downloads": -1,
            "filename": "qpmpc-3.0.1.tar.gz",
            "has_sig": false,
            "md5_digest": "e8c7b7420d518ea08e1c07326f5afadc",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 44594,
            "upload_time": "2023-12-21T14:34:57",
            "upload_time_iso_8601": "2023-12-21T14:34:57.370863Z",
            "url": "https://files.pythonhosted.org/packages/98/c7/4199bca033e81d4548af37417f9ac40bc925eb93c6ca0383fa83480a868a/qpmpc-3.0.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-12-21 14:34:57",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "stephane-caron",
    "github_project": "qpmpc",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "tox": true,
    "lcname": "qpmpc"
}
        
Elapsed time: 0.16947s