{"id":33130971,"url":"https://github.com/bdaiinstitute/spatialmath-python","last_synced_at":"2026-01-17T05:51:00.243Z","repository":{"id":39705081,"uuid":"258342458","full_name":"bdaiinstitute/spatialmath-python","owner":"bdaiinstitute","description":"Create,  manipulate and convert representations of position and orientation in 2D or 3D using Python","archived":false,"fork":false,"pushed_at":"2025-11-20T21:47:16.000Z","size":33441,"stargazers_count":610,"open_issues_count":16,"forks_count":94,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-12-27T03:16:19.988Z","etag":null,"topics":["2d","3d","animation","euler-angles","graphics","math","python","quaternion","robot","roll-pitch-yaw-angles","rotation-matrix","so3","transform"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bdaiinstitute.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-04-23T22:09:44.000Z","updated_at":"2025-12-23T14:38:57.000Z","dependencies_parsed_at":"2023-02-16T16:15:35.583Z","dependency_job_id":"e6a3d7b7-3211-4a58-a922-c9f4456cd237","html_url":"https://github.com/bdaiinstitute/spatialmath-python","commit_stats":null,"previous_names":["bdaiinstitute/spatialmath-python","petercorke/spatialmath-python"],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/bdaiinstitute/spatialmath-python","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdaiinstitute%2Fspatialmath-python","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdaiinstitute%2Fspatialmath-python/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdaiinstitute%2Fspatialmath-python/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdaiinstitute%2Fspatialmath-python/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bdaiinstitute","download_url":"https://codeload.github.com/bdaiinstitute/spatialmath-python/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdaiinstitute%2Fspatialmath-python/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28501328,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T04:31:57.058Z","status":"ssl_error","status_checked_at":"2026-01-17T04:31:45.816Z","response_time":85,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["2d","3d","animation","euler-angles","graphics","math","python","quaternion","robot","roll-pitch-yaw-angles","rotation-matrix","so3","transform"],"created_at":"2025-11-15T09:00:43.977Z","updated_at":"2026-01-17T05:51:00.109Z","avatar_url":"https://github.com/bdaiinstitute.png","language":"Python","readme":"# Spatial Maths for Python\n\n[![A Python Robotics Package](https://raw.githubusercontent.com/petercorke/robotics-toolbox-python/master/.github/svg/py_collection.min.svg)](https://github.com/petercorke/robotics-toolbox-python)\n[![QUT Centre for Robotics Open Source](https://github.com/qcr/qcr.github.io/raw/master/misc/badge.svg)](https://qcr.github.io)\n\n[![PyPI version](https://badge.fury.io/py/spatialmath-python.svg)](https://badge.fury.io/py/spatialmath-python)\n[![Anaconda version](https://anaconda.org/conda-forge/spatialmath-python/badges/version.svg)](https://anaconda.org/conda-forge/spatialmath-python)\n![Python Version](https://img.shields.io/pypi/pyversions/spatialmath-python.svg)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n[![Build Status](https://github.com/bdaiinstitute/spatialmath-python/actions/workflows/master.yml/badge.svg?branch=master)](https://github.com/bdaiinstitute/spatialmath-python/actions/workflows/master.yml?query=workflow%3Abuild+branch%3Amaster)\n[![Coverage](https://codecov.io/github/bdaiinstitute/spatialmath-python/graph/badge.svg?token=W15FGBA059)](https://codecov.io/github/bdaiinstitute/spatialmath-python)\n[![PyPI - Downloads](https://img.shields.io/pypi/dw/spatialmath-python)](https://pypistats.org/packages/spatialmath-python)\n[![GitHub stars](https://img.shields.io/github/stars/bdaiinstitute/spatialmath-python.svg?style=social\u0026label=Star)](https://GitHub.com/bdaiinstitute/spatialmath-python/stargazers/)\n\n\n\n\u003ctable style=\"border:0px\"\u003e\n\u003ctr style=\"border:0px\"\u003e\n\u003ctd style=\"border:0px\"\u003e\n\u003cimg src=\"https://github.com/bdaiinstitute/spatialmath-python/raw/master/docs/figs/CartesianSnakes_LogoW.png\" width=\"200\"\u003e\u003c/td\u003e\n\u003ctd style=\"border:0px\"\u003e\nA Python implementation of the \u003ca href=\"https://github.com/petercorke/spatial-math\"\u003eSpatial Math Toolbox for MATLAB\u003csup\u003e\u0026reg;\u003c/sup\u003e\u003c/a\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/bdaiinstitute/spatialmath-python\"\u003eGitHub repository \u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://bdaiinstitute.github.io/spatialmath-python\"\u003eDocumentation\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=https://github.com/bdaiinstitute/spatialmath-python/discussions/categories/changes\u003eRecent changes\u003c/a\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/bdaiinstitute/spatialmath-python/wiki\"\u003eWiki (examples and details)\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"installation#\"\u003eInstallation\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\nSpatial mathematics capability underpins all of robotics and robotic vision where we need to describe the position, orientation or pose of objects in 2D or 3D spaces.\n\n\n\n# What it does\n\nThe package provides classes to represent pose and orientation in 3D and 2D\nspace:\n\n| Represents   | in 3D            |   in 2D  |\n| ------------ | ---------------- | -------- |\n| pose         | ``SE3`` ``Twist3`` ``UnitDualQuaternion``   |   ``SE2`` ``Twist2`` |\n| orientation  | ``SO3`` ``UnitQuaternion`` |            ``SO2``  |\n\n\nMore specifically:\n\n * `SE3` matrices belonging to the group $\\mathbf{SE}(3)$ for position and orientation (pose) in 3-dimensions\n * `SO3` matrices belonging to the group $\\mathbf{SO}(3)$ for orientation in 3-dimensions\n *  `UnitQuaternion` belonging to the group $\\mathbf{S}^3$ for orientation in 3-dimensions\n * `Twist3` vectors belonging to the group $\\mathbf{se}(3)$ for pose in 3-dimensions\n * `UnitDualQuaternion` maps to the group $\\mathbf{SE}(3)$ for position and orientation (pose) in 3-dimensions\n * `SE2` matrices belonging to the group $\\mathbf{SE}(2)$ for position and orientation (pose) in 2-dimensions\n * `SO2` matrices belonging to the group $\\mathbf{SO}(2)$ for orientation in 2-dimensions\n * `Twist2` vectors belonging to the group $\\mathbf{se}(2)$ for pose in 2-dimensions\n\n\nThese classes provide convenience and type safety, as well as methods and overloaded operators to support:\n\n * composition, using the `*` operator\n * point transformation, using the `*` operator\n * exponent, using the `**` operator\n * normalization\n * inversion\n * connection to the Lie algebra via matrix exponential and logarithm operations\n * conversion of orientation to/from Euler angles, roll-pitch-yaw angles and angle-axis forms.\n * list operations such as append, insert and get\n\nThese are layered over a set of base functions that perform many of the same operations but represent data explicitly in terms of `numpy` arrays.\n\nThe class, method and functions names largely mirror those of the MATLAB toolboxes, and the semantics are quite similar.\n\n![trplot](https://github.com/bdaiinstitute/spatialmath-python/raw/master/docs/figs/fig1.png)\n\n![animation video](./docs/figs/animate.gif)\n\n# Citing\n\nCheck out our ICRA 2021 paper on [IEEE Xplore](https://ieeexplore.ieee.org/document/9561366) or get the PDF from [Peter's website](https://bit.ly/icra_rtb).  This describes the [Robotics Toolbox for Python](https://github.com/petercorke/robotics-toolbox-python) as well Spatial Maths.\n\nIf the toolbox helped you in your research, please cite\n\n```\n@inproceedings{rtb,\n  title={Not your grandmother’s toolbox--the Robotics Toolbox reinvented for Python},\n  author={Corke, Peter and Haviland, Jesse},\n  booktitle={2021 IEEE International Conference on Robotics and Automation (ICRA)},\n  pages={11357--11363},\n  year={2021},\n  organization={IEEE}\n}\n```\n\n\u003cbr\u003e\n\n\u003ca id='6'\u003e\u003c/a\u003e\n\n## Using the Toolbox in your Open Source Code?\n\nIf you are using the Toolbox in your open source code, feel free to add our badge to your readme!\n\n[![Powered by the Spatial Math Toolbox](https://github.com/bdaiinstitute/spatialmath-python/raw/master/.github/svg/sm_powered.min.svg)](https://github.com/bdaiinstitute/spatialmath-python)\n\nSimply copy the following\n\n```\n[![Powered by the Spatial Math Toolbox](https://github.com/bdaiinstitute/spatialmath-python/raw/master/.github/svg/sm_powered.min.svg)](https://github.com/bdaiinstitute/spatialmath-python)\n```\n\n\n# Installation\n\n## Using pip\n\nInstall a snapshot from PyPI\n\n```\npip install spatialmath-python\n```\n\nNote that if you are using ROS2, you may run into version conflicts when using `rosdep`, particularly\nconcerning `matplotlib`. If this happens, you can enable optional version pinning with\n\n```\npip install spatialmath-python[ros-humble]\n```\n\n## From GitHub\n\nInstall the current code base from GitHub and pip install a link to that cloned copy\n\n```\ngit clone https://github.com/bdaiinstitute/spatialmath-python.git\ncd spatialmath-python\npip install -e .\n# Optional: if you would like to contribute and commit code changes to the repository,\n# pre-commit install\n```\n\n## Dependencies\n\n`numpy`, `scipy`, `matplotlib`, `ffmpeg` (if rendering animations as a movie)\n\n# Examples\n\n\n## High-level classes\n\nThese classes abstract the low-level numpy arrays into objects that obey the rules associated with the mathematical groups SO(2), SE(2), SO(3), SE(3) as well as twists and quaternions.\n\nUsing classes ensures type safety, for example it stops us mixing a 2D homogeneous transformation with a 3D rotation matrix -- both of which are 3x3 matrices.  It also ensures that the internal matrix representation is always a valid member of the relevant group.\n\nFor example, to create an object representing a rotation of 0.3 radians about the x-axis is simply\n\n```python\n\u003e\u003e\u003e from spatialmath import SO3, SE3\n\u003e\u003e\u003e R1 = SO3.Rx(0.3)\n\u003e\u003e\u003e R1\n   1         0         0\n   0         0.955336 -0.29552\n   0         0.29552   0.955336\n```\nwhile a rotation of 30 deg about the z-axis is\n\n```python\n\u003e\u003e\u003e R2 = SO3.Rz(30, 'deg')\n\u003e\u003e\u003e R2\n   0.866025 -0.5       0\n   0.5       0.866025  0\n   0         0         1\n```\nand the composition of these two rotations is\n\n```python\n\u003e\u003e\u003e R = R1 * R2\n   0.866025 -0.5       0\n   0.433013  0.75     -0.5\n   0.25      0.433013  0.866025\n```\n\nWe can find the corresponding Euler angles (in radians)\n\n```python\n\u003e\u003e R.eul()\narray([-1.57079633,  0.52359878,  2.0943951 ])\n```\n\nFrequently in robotics we want a sequence, a trajectory, of rotation matrices or poses. These pose classes inherit capability from the `list` class\n\n```python\n\u003e\u003e\u003e R = SO3()   # the null rotation or identity matrix\n\u003e\u003e\u003e R.append(R1)\n\u003e\u003e\u003e R.append(R2)\n\u003e\u003e\u003e len(R)\n 3\n\u003e\u003e\u003e R[1]\n   1         0         0\n   0         0.955336 -0.29552\n   0         0.29552   0.955336\n```\nand this can be used in `for` loops and list comprehensions.\n\nAn alternative way of constructing this would be (`R1`, `R2` defined above)\n\n```python\n\u003e\u003e\u003e R = SO3( [ SO3(), R1, R2 ] )\n\u003e\u003e\u003e len(R)\n 3\n```\n\nMany of the constructors such as `.Rx`, `.Ry` and `.Rz` support vectorization\n\n```python\n\u003e\u003e\u003e R = SO3.Rx( np.arange(0, 2*np.pi, 0.2))\n\u003e\u003e\u003e len(R)\n 32\n```\nwhich has created, in a single line, a list of rotation matrices.\n\nVectorization also applies to the operators, for instance\n\n```python\n\u003e\u003e\u003e A = R * SO3.Ry(0.5)\n\u003e\u003e\u003e len(R)\n 32\n```\nwill produce a result where each element is the product of each element of the left-hand side with the right-hand side, ie. `R[i] * SO3.Ry(0.5)`.\n\nSimilarly\n\n```python\n\u003e\u003e\u003e A = SO3.Ry(0.5) * R\n\u003e\u003e\u003e len(R)\n 32\n```\nwill produce a result where each element is the product of the left-hand side with each element of the right-hand side , ie. `SO3.Ry(0.5) * R[i] `.\n\nFinally\n\n```python\n\u003e\u003e\u003e A = R * R\n\u003e\u003e\u003e len(R)\n 32\n```\nwill produce a result where each element is the product of each element of the left-hand side with each element of the right-hand side , ie. `R[i] * R[i] `.\n\nThe underlying representation of these classes is a numpy matrix, but the class ensures that the structure of that matrix is valid for the particular group represented: SO(2), SE(2), SO(3), SE(3).  Any operation that is not valid for the group will return a matrix rather than a pose class, for example\n\n```python\n\u003e\u003e\u003e SO3.Rx(0.3) * 2\narray([[ 2.        ,  0.        ,  0.        ],\n       [ 0.        ,  1.91067298, -0.59104041],\n       [ 0.        ,  0.59104041,  1.91067298]])\n\n\u003e\u003e\u003e SO3.Rx(0.3) - 1\narray([[ 0.        , -1.        , -1.        ],\n       [-1.        , -0.04466351, -1.29552021],\n       [-1.        , -0.70447979, -0.04466351]])\n```\n\nWe can print and plot these objects as well\n\n```\n\u003e\u003e\u003e T = SE3(1,2,3) * SE3.Rx(30, 'deg')\n\u003e\u003e\u003e T.print()\n   1         0         0         1\n   0         0.866025 -0.5       2\n   0         0.5       0.866025  3\n   0         0         0         1\n\n\u003e\u003e\u003e T.printline()\nt =        1,        2,        3; rpy/zyx =       30,        0,        0 deg\n\n\u003e\u003e\u003e T.plot()\n```\n\n![trplot](https://github.com/bdaiinstitute/spatialmath-python/raw/master/docs/figs/fig1.png)\n\n`printline` is a compact single line format for tabular listing, whereas `print` shows the underlying matrix and for consoles that support it, it is colorised, with rotational elements in red and translational elements in blue.\n\nFor more detail checkout the shipped Python notebooks:\n\n* [gentle introduction](https://github.com/bdaiinstitute/spatialmath-python/blob/master/notebooks/gentle-introduction.ipynb)\n* [deeper introduction](https://github.com/bdaiinstitute/spatialmath-python/blob/master/notebooks/introduction.ipynb)\n\n\nYou can browse it statically through the links above, or clone the toolbox and run them interactively using [Jupyter](https://jupyter.org) or [JupyterLab](https://jupyter.org).\n\n\n## Low-level spatial math\n\n\nImport the low-level transform functions\n\n```\n\u003e\u003e\u003e from spatialmath.base import *\n```\n\nWe can create a 3D rotation matrix\n\n```\n\u003e\u003e\u003e rotx(0.3)\narray([[ 1.        ,  0.        ,  0.        ],\n       [ 0.        ,  0.95533649, -0.29552021],\n       [ 0.        ,  0.29552021,  0.95533649]])\n\n\u003e\u003e\u003e rotx(30, unit='deg')\narray([[ 1.       ,  0.       ,  0.       ],\n       [ 0.       ,  0.8660254, -0.5      ],\n       [ 0.       ,  0.5      ,  0.8660254]])\n```\nThe results are `numpy` arrays so to perform matrix multiplication you need to use the `@` operator, for example\n\n```\nrotx(0.3) @ roty(0.2)\n```\n\nWe also support multiple ways of passing vector information to functions that require it:\n\n* as separate positional arguments\n\n```\ntransl2(1, 2)\narray([[1., 0., 1.],\n       [0., 1., 2.],\n       [0., 0., 1.]])\n```\n\n* as a list or a tuple\n\n```\ntransl2( [1,2] )\narray([[1., 0., 1.],\n       [0., 1., 2.],\n       [0., 0., 1.]])\n\ntransl2( (1,2) )\nOut[444]:\narray([[1., 0., 1.],\n       [0., 1., 2.],\n       [0., 0., 1.]])\n```\n\n* or as a `numpy` array\n\n```\ntransl2( np.array([1,2]) )\nOut[445]:\narray([[1., 0., 1.],\n       [0., 1., 2.],\n       [0., 0., 1.]])\n```\n\n\nThere is a single module that deals with quaternions, unit or not, and the representation is a `numpy` array of four elements.  As above, functions can accept the `numpy` array, a list, dict or `numpy` row or column vectors.\n\n```\n\u003e\u003e\u003e from spatialmath.base.quaternion import *\n\u003e\u003e\u003e q = qqmul([1,2,3,4], [5,6,7,8])\n\u003e\u003e\u003e q\narray([-60,  12,  30,  24])\n\u003e\u003e\u003e qprint(q)\n-60.000000 \u003c 12.000000, 30.000000, 24.000000 \u003e\n\u003e\u003e\u003e qnorm(q)\n72.24956747275377\n```\n\n## Graphics\n\n![trplot](https://github.com/bdaiinstitute/spatialmath-python/raw/master/docs/figs/transforms3d.png)\n\nThe functions support various plotting styles\n\n```\ntrplot( transl(1,2,3), frame='A', rviz=True, width=1, dims=[0, 10, 0, 10, 0, 10])\ntrplot( transl(3,1, 2), color='red', width=3, frame='B')\ntrplot( transl(4, 3, 1)@trotx(math.pi/3), color='green', frame='c', dims=[0,4,0,4,0,4])\n```\n\nAnimation is straightforward\n\n```\ntranimate(transl(4, 3, 4)@trotx(2)@troty(-2), frame='A', arrow=False, dims=[0, 5], nframes=200)\n```\n\nand it can be saved to a file by\n\n```\ntranimate(transl(4, 3, 4)@trotx(2)@troty(-2), frame='A', arrow=False, dims=[0, 5], nframes=200, movie='out.mp4')\n```\n\n![animation video](./docs/figs/animate.gif)\n\nAt the moment we can only save as an MP4, but the following incantation will covert that to an animated GIF for embedding in web pages\n\n```\nffmpeg -i out -r 20 -vf \"fps=10,scale=640:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse\" out.gif\n```\n\nFor use in a Jupyter notebook, or on Colab, you can display an animation by\n```\nfrom IPython.core.display import HTML\nHTML(tranimate(transl(4, 3, 4)@trotx(2)@troty(-2), frame='A', arrow=False, dims=[0, 5], nframes=200, movie=True))\n```\nThe `movie=True` option causes `tranimate` to output an HTML5 fragment which\nis displayed inline by the `HTML` function.\n\n## Symbolic support\n\nSome functions have support for symbolic variables, for example\n\n```\nimport sympy\n\ntheta = sym.symbols('theta')\nprint(rotx(theta))\n[[1 0 0]\n [0 cos(theta) -sin(theta)]\n [0 sin(theta) cos(theta)]]\n```\n\nThe resulting `numpy` array is an array of symbolic objects not numbers \u0026ndash; the constants are also symbolic objects.  You can read the elements of the matrix\n\n```\na = T[0,0]\n\na\nOut[258]: 1\n\ntype(a)\nOut[259]: int\n\na = T[1,1]\na\nOut[256]:\ncos(theta)\ntype(a)\nOut[255]: cos\n```\nWe see that the symbolic constants are converted back to Python numeric types on read.\n\nSimilarly when we assign an element or slice of the symbolic matrix to a numeric value, they are converted to symbolic constants on the way in.\n\n## History \u0026 Contributors\n\nThis package was originally created by [Peter Corke](https://github.com/petercorke) and [Jesse Haviland](https://github.com/jhavl) and was inspired by the [Spatial Math Toolbox for MATLAB](https://github.com/petercorke/spatialmath-matlab).  It supports the textbook [Robotics, Vision \u0026 Control in Python 3e](https://github.com/petercorke/RVC3-python).\n\nThe package is now a collaboration with [Boston Dynamics AI Institute](https://theaiinstitute.com/).\n","funding_links":[],"categories":["[Libraries](#awesome-robotics-libraries)"],"sub_categories":["[Math](#awesome-robotics-libraries)"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbdaiinstitute%2Fspatialmath-python","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbdaiinstitute%2Fspatialmath-python","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbdaiinstitute%2Fspatialmath-python/lists"}