{
    "nbformat": 4,
    "nbformat_minor": 5,
    "metadata": {
        "kernelspec": {
            "display_name": "Python",
            "language": "python",
            "name": "python"
        },
        "language_info": {
            "name": "python"
        }
    },
    "cells": [
        {
            "id": "9826f056",
            "cell_type": "markdown",
            "source": "<div class='alert alert-warning'>\n\nSciPy's interactive examples with Jupyterlite are experimental and may not always work as expected. Execution of cells containing imports may result in large downloads (up to 60MB of content for the first import from SciPy). Load times when importing from SciPy may take roughly 10-20 seconds. If you notice any problems, feel free to open an [issue](https://github.com/scipy/scipy/issues/new/choose).\n\n</div>",
            "metadata": {}
        },
        {
            "id": "e1c82d72",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "from scipy.spatial.transform import Rotation as R\nimport numpy as np",
            "outputs": []
        },
        {
            "id": "c462ee0b",
            "cell_type": "markdown",
            "source": "A `Rotation` instance can be initialized in any of the above formats and\nconverted to any of the others. The underlying object is independent of the\nrepresentation used for initialization.\n\nConsider a counter-clockwise rotation of 90 degrees about the z-axis. This\ncorresponds to the following quaternion (in scalar-last format):\n",
            "metadata": {}
        },
        {
            "id": "238d87ad",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r = R.from_quat([0, 0, np.sin(np.pi/4), np.cos(np.pi/4)])",
            "outputs": []
        },
        {
            "id": "ea0a4057",
            "cell_type": "markdown",
            "source": "The rotation can be expressed in any of the other formats:\n",
            "metadata": {}
        },
        {
            "id": "580d5447",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r.as_matrix()",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([[ 2.22044605e-16, -1.00000000e+00,  0.00000000e+00],\n[ 1.00000000e+00,  2.22044605e-16,  0.00000000e+00],\n[ 0.00000000e+00,  0.00000000e+00,  1.00000000e+00]])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "fd0905ba",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r.as_rotvec()",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([0.        , 0.        , 1.57079633])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "8a209eef",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r.as_euler('zyx', degrees=True)",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([90.,  0.,  0.])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "aa3eb8c8",
            "cell_type": "markdown",
            "source": "The same rotation can be initialized using a rotation matrix:\n",
            "metadata": {}
        },
        {
            "id": "82634ade",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r = R.from_matrix([[0, -1, 0],\n                   [1, 0, 0],\n                   [0, 0, 1]])",
            "outputs": []
        },
        {
            "id": "6b8f3afe",
            "cell_type": "markdown",
            "source": "Representation in other formats:\n",
            "metadata": {}
        },
        {
            "id": "10003913",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r.as_quat()",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([0.        , 0.        , 0.70710678, 0.70710678])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "c57dcda6",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r.as_rotvec()",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([0.        , 0.        , 1.57079633])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "132da038",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r.as_euler('zyx', degrees=True)",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([90.,  0.,  0.])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "07707c75",
            "cell_type": "markdown",
            "source": "The rotation vector corresponding to this rotation is given by:\n",
            "metadata": {}
        },
        {
            "id": "4596fad4",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r = R.from_rotvec(np.pi/2 * np.array([0, 0, 1]))",
            "outputs": []
        },
        {
            "id": "66307c1e",
            "cell_type": "markdown",
            "source": "Representation in other formats:\n",
            "metadata": {}
        },
        {
            "id": "4430a0eb",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r.as_quat()",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([0.        , 0.        , 0.70710678, 0.70710678])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "e8e52ba2",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r.as_matrix()",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([[ 2.22044605e-16, -1.00000000e+00,  0.00000000e+00],\n       [ 1.00000000e+00,  2.22044605e-16,  0.00000000e+00],\n       [ 0.00000000e+00,  0.00000000e+00,  1.00000000e+00]])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "7c0ef165",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r.as_euler('zyx', degrees=True)",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([90.,  0.,  0.])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "8696c2a7",
            "cell_type": "markdown",
            "source": "The ``from_euler`` method is quite flexible in the range of input formats\nit supports. Here we initialize a single rotation about a single axis:\n",
            "metadata": {}
        },
        {
            "id": "6751a25e",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r = R.from_euler('z', 90, degrees=True)",
            "outputs": []
        },
        {
            "id": "0626d120",
            "cell_type": "markdown",
            "source": "Again, the object is representation independent and can be converted to any\nother format:\n",
            "metadata": {}
        },
        {
            "id": "73c31793",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r.as_quat()",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([0.        , 0.        , 0.70710678, 0.70710678])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "b73875e1",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r.as_matrix()",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([[ 2.22044605e-16, -1.00000000e+00,  0.00000000e+00],\n       [ 1.00000000e+00,  2.22044605e-16,  0.00000000e+00],\n       [ 0.00000000e+00,  0.00000000e+00,  1.00000000e+00]])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "88601fc3",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r.as_rotvec()",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([0.        , 0.        , 1.57079633])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "af6e56b5",
            "cell_type": "markdown",
            "source": "It is also possible to initialize multiple rotations in a single instance\nusing any of the ``from_...`` functions. Here we initialize a stack of 3\nrotations using the ``from_euler`` method:\n",
            "metadata": {}
        },
        {
            "id": "aa86daec",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r = R.from_euler('zyx', [\n[90, 0, 0],\n[0, 45, 0],\n[45, 60, 30]], degrees=True)",
            "outputs": []
        },
        {
            "id": "91787cb6",
            "cell_type": "markdown",
            "source": "The other representations also now return a stack of 3 rotations. For\nexample:\n",
            "metadata": {}
        },
        {
            "id": "1795473b",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r.as_quat()",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([[0.        , 0.        , 0.70710678, 0.70710678],\n       [0.        , 0.38268343, 0.        , 0.92387953],\n       [0.39190384, 0.36042341, 0.43967974, 0.72331741]])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "3c82c491",
            "cell_type": "markdown",
            "source": "Applying the above rotations onto a vector:\n",
            "metadata": {}
        },
        {
            "id": "91082167",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "v = [1, 2, 3]\nr.apply(v)",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([[-2.        ,  1.        ,  3.        ],\n       [ 2.82842712,  2.        ,  1.41421356],\n       [ 2.24452282,  0.78093109,  2.89002836]])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "ff9892a3",
            "cell_type": "markdown",
            "source": "A `Rotation` instance can be indexed and sliced as if it were a single\n1D array or list:\n",
            "metadata": {}
        },
        {
            "id": "3f5422d2",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r.as_quat()",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([[0.        , 0.        , 0.70710678, 0.70710678],\n       [0.        , 0.38268343, 0.        , 0.92387953],\n       [0.39190384, 0.36042341, 0.43967974, 0.72331741]])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "43e42105",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "p = r[0]\np.as_matrix()",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([[ 2.22044605e-16, -1.00000000e+00,  0.00000000e+00],\n       [ 1.00000000e+00,  2.22044605e-16,  0.00000000e+00],\n       [ 0.00000000e+00,  0.00000000e+00,  1.00000000e+00]])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "4e2236f4",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "q = r[1:3]\nq.as_quat()",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([[0.        , 0.38268343, 0.        , 0.92387953],\n       [0.39190384, 0.36042341, 0.43967974, 0.72331741]])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "d1af9827",
            "cell_type": "markdown",
            "source": "In fact it can be converted to numpy.array:\n",
            "metadata": {}
        },
        {
            "id": "9f210cdf",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r_array = np.asarray(r)\nr_array.shape",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "(3,)"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "d3a155b3",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r_array[0].as_matrix()",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([[ 2.22044605e-16, -1.00000000e+00,  0.00000000e+00],\n       [ 1.00000000e+00,  2.22044605e-16,  0.00000000e+00],\n       [ 0.00000000e+00,  0.00000000e+00,  1.00000000e+00]])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "c68c75c0",
            "cell_type": "markdown",
            "source": "Multiple rotations can be composed using the ``*`` operator:\n",
            "metadata": {}
        },
        {
            "id": "ae0e6fc7",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r1 = R.from_euler('z', 90, degrees=True)\nr2 = R.from_rotvec([np.pi/4, 0, 0])\nv = [1, 2, 3]\nr2.apply(r1.apply(v))",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([-2.        , -1.41421356,  2.82842712])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "e8e16db3",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r3 = r2 * r1 # Note the order\nr3.apply(v)",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([-2.        , -1.41421356,  2.82842712])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "d5bbd5bc",
            "cell_type": "markdown",
            "source": "A rotation can be composed with itself using the ``**`` operator:\n",
            "metadata": {}
        },
        {
            "id": "ffc423e0",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "p = R.from_rotvec([1, 0, 0])\nq = p ** 2\nq.as_rotvec()",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([2., 0., 0.])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "ca5008e2",
            "cell_type": "markdown",
            "source": "Finally, it is also possible to invert rotations:\n",
            "metadata": {}
        },
        {
            "id": "cf8954fd",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r1 = R.from_euler('z', [90, 45], degrees=True)\nr2 = r1.inv()\nr2.as_euler('zyx', degrees=True)",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([[-90.,   0.,   0.],\n       [-45.,   0.,   0.]])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "689edad5",
            "cell_type": "markdown",
            "source": "The following function can be used to plot rotations with Matplotlib by\nshowing how they transform the standard x, y, z coordinate axes:\n",
            "metadata": {}
        },
        {
            "id": "ac4b8942",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "import matplotlib.pyplot as plt",
            "outputs": []
        },
        {
            "id": "98c47a5b",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "def plot_rotated_axes(ax, r, name=None, offset=(0, 0, 0), scale=1):\n    colors = (\"#FF6666\", \"#005533\", \"#1199EE\")  # Colorblind-safe RGB\n    loc = np.array([offset, offset])\n    for i, (axis, c) in enumerate(zip((ax.xaxis, ax.yaxis, ax.zaxis),\n                                      colors)):\n        axlabel = axis.axis_name\n        axis.set_label_text(axlabel)\n        axis.label.set_color(c)\n        axis.line.set_color(c)\n        axis.set_tick_params(colors=c)\n        line = np.zeros((2, 3))\n        line[1, i] = scale\n        line_rot = r.apply(line)\n        line_plot = line_rot + loc\n        ax.plot(line_plot[:, 0], line_plot[:, 1], line_plot[:, 2], c)\n        text_loc = line[1]*1.2\n        text_loc_rot = r.apply(text_loc)\n        text_plot = text_loc_rot + loc[0]\n        ax.text(*text_plot, axlabel.upper(), color=c,\n                va=\"center\", ha=\"center\")\n    ax.text(*offset, name, color=\"k\", va=\"center\", ha=\"center\",\n            bbox={\"fc\": \"w\", \"alpha\": 0.8, \"boxstyle\": \"circle\"})",
            "outputs": []
        },
        {
            "id": "17bc6c64",
            "cell_type": "markdown",
            "source": "Create three rotations - the identity and two Euler rotations using\nintrinsic and extrinsic conventions:\n",
            "metadata": {}
        },
        {
            "id": "8c7d205b",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "r0 = R.identity()\nr1 = R.from_euler(\"ZYX\", [90, -30, 0], degrees=True)  # intrinsic\nr2 = R.from_euler(\"zyx\", [90, -30, 0], degrees=True)  # extrinsic",
            "outputs": []
        },
        {
            "id": "2306d4eb",
            "cell_type": "markdown",
            "source": "Add all three rotations to a single plot:\n",
            "metadata": {}
        },
        {
            "id": "c8a4b95e",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "ax = plt.figure().add_subplot(projection=\"3d\", proj_type=\"ortho\")\nplot_rotated_axes(ax, r0, name=\"r0\", offset=(0, 0, 0))\nplot_rotated_axes(ax, r1, name=\"r1\", offset=(3, 0, 0))\nplot_rotated_axes(ax, r2, name=\"r2\", offset=(6, 0, 0))\n_ = ax.annotate(\n    \"r0: Identity Rotation\\n\"\n    \"r1: Intrinsic Euler Rotation (ZYX)\\n\"\n    \"r2: Extrinsic Euler Rotation (zyx)\",\n    xy=(0.6, 0.7), xycoords=\"axes fraction\", ha=\"left\"\n)\nax.set(xlim=(-1.25, 7.25), ylim=(-1.25, 1.25), zlim=(-1.25, 1.25))\nax.set(xticks=range(-1, 8), yticks=[-1, 0, 1], zticks=[-1, 0, 1])\nax.set_aspect(\"equal\", adjustable=\"box\")\nax.figure.set_size_inches(6, 5)\nplt.tight_layout()",
            "outputs": []
        },
        {
            "id": "48a11865",
            "cell_type": "markdown",
            "source": "Show the plot:\n",
            "metadata": {}
        },
        {
            "id": "1c5c1b8c",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "plt.show()",
            "outputs": []
        },
        {
            "id": "7f5aae0f",
            "cell_type": "markdown",
            "source": "These examples serve as an overview into the `Rotation` class and highlight\nmajor functionalities. For more thorough examples of the range of input and\noutput formats supported, consult the individual method's examples.\n",
            "metadata": {}
        }
    ]
}