diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..c5818f3 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,30 @@ +FROM mcr.microsoft.com/devcontainers/base:ubuntu-24.04 + +ARG DEBIAN_FRONTEND=noninteractive +ARG USER=vscode +RUN apt update \ + && apt install -y --no-install-recommends curl wget git sudo build-essential libssl-dev zlib1g-dev libjpeg-dev libpng-dev libbz2-dev libreadline-dev libsqlite3-dev libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev \ + && apt autoremove -y \ + && rm -rf /var/lib/apt/lists/* \ + && usermod -s /usr/bin/zsh ${USER} + +USER ${USER} +ARG HOME="/home/${USER}" +WORKDIR ${HOME} + +ARG PYTHON_VERSION=3.12 +ENV PYENV_ROOT=${HOME}/.pyenv +ARG PYENV_PATH="${PYENV_ROOT}/bin:${PYENV_ROOT}/shims" +ARG PDM_PATH="${HOME}/.local/bin" +ENV PATH="${PYENV_PATH}:${PDM_PATH}:$PATH" +RUN set -x \ + && curl http://pyenv.run | bash \ + && echo 'eval "$(pyenv init -)"' >>${HOME}/.zshrc \ + && pyenv install -v ${PYTHON_VERSION} \ + && pyenv global ${PYTHON_VERSION} + +ARG ZSH_CUSTOM=${HOME}/.oh-my-zsh/custom +RUN curl -sSL https://pdm.fming.dev/install-pdm.py | python - \ + && mkdir ${ZSH_CUSTOM}/plugins/pdm \ + && pdm completion zsh > ${ZSH_CUSTOM}/plugins/pdm/_pdm \ + && sed -i "s|^plugins=(|&pdm |" ${HOME}/.zshrc diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..bafde04 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,55 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/python +{ + "name": "Python 3", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + //"image": "mcr.microsoft.com/devcontainers/python:1-3.12-bullseye", + "build": { + "dockerfile": "Dockerfile" + }, + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + // Add customizations for the editor + "customizations": { + "vscode": { + "extensions": [ + "bierner.markdown-mermaid", + "bpruitt-goddard.mermaid-markdown-syntax-highlighting", + "DavidAnson.vscode-markdownlint", + "donjayamanne.githistory", + "eamodio.gitlens", + "formulahendry.auto-close-tag", + "GitHub.copilot-chat", + "GitHub.copilot", + "mhutchie.git-graph", + "ms-python.debugpy", + "ms-python.isort", + "ms-python.python", + "ms-python.vscode-pylance", + "redhat.vscode-yaml", + "tamasfe.even-better-toml" + ], + "settings": { + "debugpy.debugJustMyCode": true, + "python.analysis.autoFormatStrings": true, + "python.analysis.inlayHints.functionReturnTypes": true, + "python.analysis.inlayHints.pytestParameters": true, + "python.analysis.inlayHints.variableTypes": true, + "python.formatting.provider": "black", + "python.linting.enabled": true, + "python.linting.mypyEnabled": true, + "python.testing.pytestArgs": [ + "." + ], + "python.testing.pytestEnabled": true, + "python.testing.unittestEnabled": false + } + } + }, + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "bash .devcontainer/post-create.sh" + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh new file mode 100644 index 0000000..7c64323 --- /dev/null +++ b/.devcontainer/post-create.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +pdm sync diff --git a/.gitignore b/.gitignore index 8265c57..ef524c5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ __pycache__/ .vscode/ +.pytest_cache/ +.venv/ + verification/linear_module_first/verification_results.xlsx verification/linear_module_first/~$verification_results.xlsx verification/linear_body_first/~$verification_simple_4w_steering.xlsx diff --git a/.pdm-python b/.pdm-python index c9002fc..cd6fb01 100644 --- a/.pdm-python +++ b/.pdm-python @@ -1 +1 @@ -D:/dev/languages/miniforge3/python.exe \ No newline at end of file +/workspaces/basic-swerve-sim/.venv/bin/python \ No newline at end of file diff --git a/pdm.lock b/pdm.lock index 085309c..0ec8f51 100644 --- a/pdm.lock +++ b/pdm.lock @@ -2,18 +2,70 @@ # It is not intended for manual editing. [metadata] -groups = ["default"] +groups = ["default", "lint", "test"] strategy = ["cross_platform", "inherit_metadata"] -lock_version = "4.4.2" -content_hash = "sha256:a69d5c54f23e8f19bede25f81d8fe3b38d67122984008263c6f2f27dd1099f1a" +lock_version = "4.5.0" +content_hash = "sha256:e7fd8de68349cd0aecbecc798ebb8b6a2e75a03bb83441fb1f056a2edae45d89" + +[[metadata.targets]] +requires_python = "==3.12.*" + +[[package]] +name = "argparse" +version = "1.4.0" +summary = "Python command-line parsing library" +groups = ["default"] +files = [ + {file = "argparse-1.4.0-py2.py3-none-any.whl", hash = "sha256:c31647edb69fd3d465a847ea3157d37bed1f95f19760b11a47aa91c04b666314"}, + {file = "argparse-1.4.0.tar.gz", hash = "sha256:62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4"}, +] + +[[package]] +name = "black" +version = "24.8.0" +requires_python = ">=3.8" +summary = "The uncompromising code formatter." +groups = ["lint"] +dependencies = [ + "click>=8.0.0", + "mypy-extensions>=0.4.3", + "packaging>=22.0", + "pathspec>=0.9.0", + "platformdirs>=2", + "tomli>=1.1.0; python_version < \"3.11\"", + "typing-extensions>=4.0.1; python_version < \"3.11\"", +] +files = [ + {file = "black-24.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7c046c1d1eeb7aea9335da62472481d3bbf3fd986e093cffd35f4385c94ae368"}, + {file = "black-24.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:649f6d84ccbae73ab767e206772cc2d7a393a001070a4c814a546afd0d423aed"}, + {file = "black-24.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b59b250fdba5f9a9cd9d0ece6e6d993d91ce877d121d161e4698af3eb9c1018"}, + {file = "black-24.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:6e55d30d44bed36593c3163b9bc63bf58b3b30e4611e4d88a0c3c239930ed5b2"}, + {file = "black-24.8.0-py3-none-any.whl", hash = "sha256:972085c618ee94f402da1af548a4f218c754ea7e5dc70acb168bfaca4c2542ed"}, + {file = "black-24.8.0.tar.gz", hash = "sha256:2500945420b6784c38b9ee885af039f5e7471ef284ab03fa35ecdde4688cd83f"}, +] + +[[package]] +name = "click" +version = "8.1.7" +requires_python = ">=3.7" +summary = "Composable command line interface toolkit" +groups = ["lint"] +dependencies = [ + "colorama; platform_system == \"Windows\"", + "importlib-metadata; python_version < \"3.8\"", +] +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] [[package]] name = "colorama" version = "0.4.6" requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" summary = "Cross-platform colored terminal text." -groups = ["default"] -marker = "sys_platform == \"win32\"" +groups = ["lint", "test"] +marker = "sys_platform == \"win32\" or platform_system == \"Windows\"" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -45,6 +97,51 @@ files = [ {file = "contourpy-1.2.1.tar.gz", hash = "sha256:4d8908b3bee1c889e547867ca4cdc54e5ab6be6d3e078556814a22457f49423c"}, ] +[[package]] +name = "coverage" +version = "7.6.1" +requires_python = ">=3.8" +summary = "Code coverage measurement for Python" +groups = ["test"] +files = [ + {file = "coverage-7.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778"}, + {file = "coverage-7.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d"}, + {file = "coverage-7.6.1-cp312-cp312-win32.whl", hash = "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5"}, + {file = "coverage-7.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb"}, + {file = "coverage-7.6.1.tar.gz", hash = "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d"}, +] + +[[package]] +name = "coverage" +version = "7.6.1" +extras = ["toml"] +requires_python = ">=3.8" +summary = "Code coverage measurement for Python" +groups = ["test"] +dependencies = [ + "coverage==7.6.1", + "tomli; python_full_version <= \"3.11.0a6\"", +] +files = [ + {file = "coverage-7.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778"}, + {file = "coverage-7.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d"}, + {file = "coverage-7.6.1-cp312-cp312-win32.whl", hash = "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5"}, + {file = "coverage-7.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb"}, + {file = "coverage-7.6.1.tar.gz", hash = "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d"}, +] + [[package]] name = "cycler" version = "0.12.1" @@ -56,18 +153,6 @@ files = [ {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, ] -[[package]] -name = "exceptiongroup" -version = "1.2.1" -requires_python = ">=3.7" -summary = "Backport of PEP 654 (exception groups)" -groups = ["default"] -marker = "python_version < \"3.11\"" -files = [ - {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, - {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, -] - [[package]] name = "fonttools" version = "4.53.0" @@ -87,27 +172,12 @@ files = [ {file = "fonttools-4.53.0.tar.gz", hash = "sha256:c93ed66d32de1559b6fc348838c7572d5c0ac1e4a258e76763a5caddd8944002"}, ] -[[package]] -name = "importlib-resources" -version = "6.4.0" -requires_python = ">=3.8" -summary = "Read resources from Python packages" -groups = ["default"] -marker = "python_version < \"3.10\"" -dependencies = [ - "zipp>=3.1.0; python_version < \"3.10\"", -] -files = [ - {file = "importlib_resources-6.4.0-py3-none-any.whl", hash = "sha256:50d10f043df931902d4194ea07ec57960f66a80449ff867bfe782b4c486ba78c"}, - {file = "importlib_resources-6.4.0.tar.gz", hash = "sha256:cdb2b453b8046ca4e3798eb1d84f3cce1446a0e8e7b5ef4efb600f19fc398145"}, -] - [[package]] name = "iniconfig" version = "2.0.0" requires_python = ">=3.7" summary = "brain-dead simple config-ini parsing" -groups = ["default"] +groups = ["test"] files = [ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, @@ -119,6 +189,9 @@ version = "1.4.5" requires_python = ">=3.7" summary = "A fast implementation of the Cassowary constraint solver" groups = ["default"] +dependencies = [ + "typing-extensions; python_version < \"3.8\"", +] files = [ {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9407b6a5f0d675e8a827ad8742e1d6b49d9c1a1da5d952a67d50ef5f4170b18d"}, {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15568384086b6df3c65353820a4473575dbad192e35010f622c6ce3eebd57af9"}, @@ -185,6 +258,17 @@ files = [ {file = "matplotlib-3.9.0.tar.gz", hash = "sha256:e6d29ea6c19e34b30fb7d88b7081f869a03014f66fe06d62cc77d5a6ea88ed7a"}, ] +[[package]] +name = "mypy-extensions" +version = "1.0.0" +requires_python = ">=3.5" +summary = "Type system extensions for programs checked with the mypy type checker." +groups = ["lint"] +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + [[package]] name = "numpy" version = "2.0.0" @@ -214,12 +298,23 @@ name = "packaging" version = "24.1" requires_python = ">=3.8" summary = "Core utilities for Python packages" -groups = ["default"] +groups = ["default", "lint", "test"] files = [ {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, ] +[[package]] +name = "pathspec" +version = "0.12.1" +requires_python = ">=3.8" +summary = "Utility library for gitignore style pattern matching of file paths." +groups = ["lint"] +files = [ + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, +] + [[package]] name = "pillow" version = "10.3.0" @@ -255,6 +350,17 @@ files = [ {file = "pillow-10.3.0.tar.gz", hash = "sha256:9d2455fbf44c914840c793e89aa82d0e1763a14253a000743719ae5946814b2d"}, ] +[[package]] +name = "platformdirs" +version = "4.2.2" +requires_python = ">=3.8" +summary = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +groups = ["lint"] +files = [ + {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, + {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, +] + [[package]] name = "plotly" version = "5.22.0" @@ -275,7 +381,7 @@ name = "pluggy" version = "1.5.0" requires_python = ">=3.8" summary = "plugin and hook calling mechanisms for python" -groups = ["default"] +groups = ["test"] files = [ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, @@ -294,21 +400,36 @@ files = [ [[package]] name = "pytest" -version = "8.2.2" +version = "8.3.2" requires_python = ">=3.8" summary = "pytest: simple powerful testing with Python" -groups = ["default"] +groups = ["test"] dependencies = [ "colorama; sys_platform == \"win32\"", "exceptiongroup>=1.0.0rc8; python_version < \"3.11\"", "iniconfig", "packaging", - "pluggy<2.0,>=1.5", + "pluggy<2,>=1.5", "tomli>=1; python_version < \"3.11\"", ] files = [ - {file = "pytest-8.2.2-py3-none-any.whl", hash = "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343"}, - {file = "pytest-8.2.2.tar.gz", hash = "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977"}, + {file = "pytest-8.3.2-py3-none-any.whl", hash = "sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5"}, + {file = "pytest-8.3.2.tar.gz", hash = "sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce"}, +] + +[[package]] +name = "pytest-cov" +version = "5.0.0" +requires_python = ">=3.8" +summary = "Pytest plugin for measuring coverage." +groups = ["test"] +dependencies = [ + "coverage[toml]>=5.2.1", + "pytest>=4.6", +] +files = [ + {file = "pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857"}, + {file = "pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652"}, ] [[package]] @@ -325,6 +446,46 @@ files = [ {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, ] +[[package]] +name = "pyyaml" +version = "6.0.2" +requires_python = ">=3.8" +summary = "YAML parser and emitter for Python" +groups = ["default"] +files = [ + {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, + {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, + {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, + {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, +] + +[[package]] +name = "scipy" +version = "1.14.1" +requires_python = ">=3.10" +summary = "Fundamental algorithms for scientific computing in Python" +groups = ["default"] +dependencies = [ + "numpy<2.3,>=1.23.5", +] +files = [ + {file = "scipy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:631f07b3734d34aced009aaf6fedfd0eb3498a97e581c3b1e5f14a04164a456d"}, + {file = "scipy-1.14.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:af29a935803cc707ab2ed7791c44288a682f9c8107bc00f0eccc4f92c08d6e07"}, + {file = "scipy-1.14.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:2843f2d527d9eebec9a43e6b406fb7266f3af25a751aa91d62ff416f54170bc5"}, + {file = "scipy-1.14.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:eb58ca0abd96911932f688528977858681a59d61a7ce908ffd355957f7025cfc"}, + {file = "scipy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30ac8812c1d2aab7131a79ba62933a2a76f582d5dbbc695192453dae67ad6310"}, + {file = "scipy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f9ea80f2e65bdaa0b7627fb00cbeb2daf163caa015e59b7516395fe3bd1e066"}, + {file = "scipy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:edaf02b82cd7639db00dbff629995ef185c8df4c3ffa71a5562a595765a06ce1"}, + {file = "scipy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:2ff38e22128e6c03ff73b6bb0f85f897d2362f8c052e3b8ad00532198fbdae3f"}, + {file = "scipy-1.14.1.tar.gz", hash = "sha256:5a275584e726026a5699459aa72f828a610821006228e841b94275c4a7c08417"}, +] + [[package]] name = "six" version = "1.16.0" @@ -346,27 +507,3 @@ files = [ {file = "tenacity-8.4.2-py3-none-any.whl", hash = "sha256:9e6f7cf7da729125c7437222f8a522279751cdfbe6b67bfe64f75d3a348661b2"}, {file = "tenacity-8.4.2.tar.gz", hash = "sha256:cd80a53a79336edba8489e767f729e4f391c896956b57140b5d7511a64bbd3ef"}, ] - -[[package]] -name = "tomli" -version = "2.0.1" -requires_python = ">=3.7" -summary = "A lil' TOML parser" -groups = ["default"] -marker = "python_version < \"3.11\"" -files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] - -[[package]] -name = "zipp" -version = "3.19.2" -requires_python = ">=3.8" -summary = "Backport of pathlib-compatible object wrapper for zip files" -groups = ["default"] -marker = "python_version < \"3.10\"" -files = [ - {file = "zipp-3.19.2-py3-none-any.whl", hash = "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c"}, - {file = "zipp-3.19.2.tar.gz", hash = "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19"}, -] diff --git a/pyproject.toml b/pyproject.toml index 8e634d3..729ac2c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,20 +1,30 @@ [project] name = "basic-swerve-sim" version = "0.1.0" -description = "Default template for PDM package" +description = "This package contains Python code that simulates the state of a wheeled mobile robot which has all wheel drive and all wheel steering" authors = [ { name = "Petrik van der Velde", email = "petrikvandervelde@gmail.com" }, ] dependencies = [ - "pytest>=8.2.2", "matplotlib>=3.9.0", "numpy>=2.0.0", "plotly>=5.22.0", + "argparse>=1.4.0", + "scipy>=1.14.1", + "pyyaml>=6.0.2", ] -requires-python = "==3.9.*" +requires-python = "==3.12.*" readme = "README.md" license = { text = "Apache-2.0" } - [tool.pdm] distribution = false + +[tool.pdm.dev-dependencies] +test = [ + "pytest>=8.3.2", + "pytest-cov>=5.0.0", +] +lint = [ + "black>=24.8.0", +] diff --git a/run_trajectory_simulation.py b/run_trajectory_simulation.py index 98d54d8..217a4e6 100644 --- a/run_trajectory_simulation.py +++ b/run_trajectory_simulation.py @@ -2,7 +2,7 @@ from os import makedirs, path from pathlib import Path -from typing import Callable, List, Mapping, NamedTuple, Tuple +from typing import List, Mapping, NamedTuple, Tuple from swerve_controller.geometry import RealNumberValueSpace from swerve_controller.profile import SingleVariableLinearProfile, SingleVariableSCurveProfile, SingleVariableTrapezoidalProfile, TransientVariableProfile import yaml @@ -547,4 +547,4 @@ def main(args=None): simulation_run_trajectories(arg_dict) if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/run_verification.py b/run_verification.py index 3103d6e..8b08895 100644 --- a/run_verification.py +++ b/run_verification.py @@ -1,18 +1,9 @@ -from abc import ABC, abstractmethod import argparse -from csv import DictReader from datetime import datetime -from distutils import util -from math import cos, isclose, isinf, pi, radians, sin, sqrt -import numpy as np -from os import makedirs, path +from os import path from pathlib import Path -from plotly.subplots import make_subplots -import plotly.graph_objects as go -import plotly.offline as py -from random import random import subprocess -from typing import List, Mapping, NamedTuple, Tuple +from typing import List, Mapping, NamedTuple import yaml from yaml.loader import SafeLoader diff --git a/src/basic_swerve_sim/__init__.py b/src/basic_swerve_sim/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/swerve_controller/control.py b/swerve_controller/control.py index 133ac52..262d7d5 100644 --- a/swerve_controller/control.py +++ b/swerve_controller/control.py @@ -1,10 +1,10 @@ from abc import ABC, abstractmethod -from typing import Mapping, List, Tuple +from typing import List, Tuple # local from .control_model import ControlModelBase from .geometry import Vector3 -from .states import BodyState, DriveModuleDesiredValues, BodyMotion +from .states import DriveModuleDesiredValues, BodyMotion class InvalidMotionCommandException(Exception): pass diff --git a/swerve_controller/control_model.py b/swerve_controller/control_model.py index 1436bc9..cac615f 100644 --- a/swerve_controller/control_model.py +++ b/swerve_controller/control_model.py @@ -5,11 +5,11 @@ import math import numpy as np from numpy.linalg import pinv -from typing import Mapping, List, Tuple +from typing import List, Tuple # local from .drive_module import DriveModule -from .geometry import LinearUnboundedSpace, Orientation, PeriodicBoundedCircularSpace, Point, Vector3 +from .geometry import LinearUnboundedSpace, PeriodicBoundedCircularSpace from .states import DriveModuleDesiredValues, DriveModuleMeasuredValues, BodyMotion # TODO replace normalize_angle and difference_between_angles with the PeriodicBoundedCircularSpace diff --git a/swerve_controller/control_profile.py b/swerve_controller/control_profile.py index a20b050..d5e77c7 100644 --- a/swerve_controller/control_profile.py +++ b/swerve_controller/control_profile.py @@ -7,13 +7,12 @@ from .errors import IncompleteTrajectoryException from .drive_module import DriveModule -from .profile import SingleVariableLinearProfile, SingleVariableMultiPointLinearProfile, ProfilePoint, SingleVariableTrapezoidalProfile, TransientVariableProfile +from .profile import SingleVariableMultiPointLinearProfile, TransientVariableProfile from .states import BodyState, DriveModuleDesiredValues, DriveModuleMeasuredValues, BodyMotion # Helper functions from typing import List, Tuple -from numbers import Real def select_directions_for_modules( drive_modules: List[DriveModule], diff --git a/swerve_controller/drive_module.py b/swerve_controller/drive_module.py index aeb86d9..5043ed6 100644 --- a/swerve_controller/drive_module.py +++ b/swerve_controller/drive_module.py @@ -1,8 +1,6 @@ -import math -from typing import Mapping, List, Tuple # local -from .geometry import Orientation, Point, Vector3 +from .geometry import Point class Wheel(object): diff --git a/swerve_controller/multi_wheel_steering_controller.py b/swerve_controller/multi_wheel_steering_controller.py index 5b44118..238dff6 100644 --- a/swerve_controller/multi_wheel_steering_controller.py +++ b/swerve_controller/multi_wheel_steering_controller.py @@ -2,10 +2,8 @@ from abc import ABC, abstractmethod import math -from turtle import forward -import numpy as np -from typing import Callable, Mapping, List, Tuple +from typing import Callable, List from swerve_controller.profile import TransientVariableProfile @@ -14,8 +12,8 @@ from .control_model import difference_between_angles, ControlModelBase, SimpleFourWheelSteeringControlModel from .control_profile import BodyControlledDriveModuleProfile, BodyMotionProfile, DriveModuleStateProfile, ModuleStateProfile from .drive_module import DriveModule -from .geometry import Point, RealNumberValueSpace -from .states import BodyState, DriveModuleDesiredValues, DriveModuleMeasuredValues, BodyMotion +from .geometry import RealNumberValueSpace +from .states import BodyState, DriveModuleDesiredValues, DriveModuleMeasuredValues class BaseSteeringController(ABC): diff --git a/swerve_controller/profile.py b/swerve_controller/profile.py index ec95462..3624640 100644 --- a/swerve_controller/profile.py +++ b/swerve_controller/profile.py @@ -1,8 +1,6 @@ from abc import ABC, abstractmethod import math -from numpy import linspace, quantile -from numpy.polynomial.polynomial import Polynomial -from scipy.interpolate import BSpline, splrep, splev +from scipy.interpolate import BSpline, splrep from typing import List, Tuple from swerve_controller.geometry import LinearUnboundedSpace, RealNumberValueSpace diff --git a/swerve_controller/states.py b/swerve_controller/states.py index 8951e6a..b79a386 100644 --- a/swerve_controller/states.py +++ b/swerve_controller/states.py @@ -1,5 +1,5 @@ import math -from typing import Mapping, List, Tuple +from typing import Tuple # local from .geometry import Orientation, Point, Vector3