From e0440dd489e342ad38395f46839f2f4a4c60b642 Mon Sep 17 00:00:00 2001 From: Beana1234 Date: Tue, 22 Oct 2024 19:04:38 +1100 Subject: [PATCH 01/20] enable pdm project --- pdm.lock | 774 +++++++++++++++++++++++++++++++++++++++++++++++++ pyproject.toml | 91 ++++++ 2 files changed, 865 insertions(+) create mode 100644 pdm.lock create mode 100644 pyproject.toml diff --git a/pdm.lock b/pdm.lock new file mode 100644 index 00000000..67b8bf6f --- /dev/null +++ b/pdm.lock @@ -0,0 +1,774 @@ +# This file is @generated by PDM. +# It is not intended for manual editing. + +[metadata] +groups = ["default"] +strategy = ["inherit_metadata"] +lock_version = "4.5.0" +content_hash = "sha256:356fe1fec85e30385f9adff0c0f3c9cb0d1e9f36b2e244cb76dd04e5ac71478c" + +[[metadata.targets]] +requires_python = ">=3.10,<3.13" + +[[package]] +name = "appdirs" +version = "1.4.4" +summary = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +files = [ + {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, + {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, +] + +[[package]] +name = "bcrypt" +version = "4.2.0" +requires_python = ">=3.7" +summary = "Modern password hashing for your software and your servers" +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +files = [ + {file = "bcrypt-4.2.0-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:096a15d26ed6ce37a14c1ac1e48119660f21b24cba457f160a4b830f3fe6b5cb"}, + {file = "bcrypt-4.2.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c02d944ca89d9b1922ceb8a46460dd17df1ba37ab66feac4870f6862a1533c00"}, + {file = "bcrypt-4.2.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d84cf6d877918620b687b8fd1bf7781d11e8a0998f576c7aa939776b512b98d"}, + {file = "bcrypt-4.2.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:1bb429fedbe0249465cdd85a58e8376f31bb315e484f16e68ca4c786dcc04291"}, + {file = "bcrypt-4.2.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:655ea221910bcac76ea08aaa76df427ef8625f92e55a8ee44fbf7753dbabb328"}, + {file = "bcrypt-4.2.0-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:1ee38e858bf5d0287c39b7a1fc59eec64bbf880c7d504d3a06a96c16e14058e7"}, + {file = "bcrypt-4.2.0-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:0da52759f7f30e83f1e30a888d9163a81353ef224d82dc58eb5bb52efcabc399"}, + {file = "bcrypt-4.2.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3698393a1b1f1fd5714524193849d0c6d524d33523acca37cd28f02899285060"}, + {file = "bcrypt-4.2.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:762a2c5fb35f89606a9fde5e51392dad0cd1ab7ae64149a8b935fe8d79dd5ed7"}, + {file = "bcrypt-4.2.0-cp37-abi3-win32.whl", hash = "sha256:5a1e8aa9b28ae28020a3ac4b053117fb51c57a010b9f969603ed885f23841458"}, + {file = "bcrypt-4.2.0-cp37-abi3-win_amd64.whl", hash = "sha256:8f6ede91359e5df88d1f5c1ef47428a4420136f3ce97763e31b86dd8280fbdf5"}, + {file = "bcrypt-4.2.0-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:c52aac18ea1f4a4f65963ea4f9530c306b56ccd0c6f8c8da0c06976e34a6e841"}, + {file = "bcrypt-4.2.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3bbbfb2734f0e4f37c5136130405332640a1e46e6b23e000eeff2ba8d005da68"}, + {file = "bcrypt-4.2.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3413bd60460f76097ee2e0a493ccebe4a7601918219c02f503984f0a7ee0aebe"}, + {file = "bcrypt-4.2.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:8d7bb9c42801035e61c109c345a28ed7e84426ae4865511eb82e913df18f58c2"}, + {file = "bcrypt-4.2.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3d3a6d28cb2305b43feac298774b997e372e56c7c7afd90a12b3dc49b189151c"}, + {file = "bcrypt-4.2.0-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:9c1c4ad86351339c5f320ca372dfba6cb6beb25e8efc659bedd918d921956bae"}, + {file = "bcrypt-4.2.0-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:27fe0f57bb5573104b5a6de5e4153c60814c711b29364c10a75a54bb6d7ff48d"}, + {file = "bcrypt-4.2.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:8ac68872c82f1add6a20bd489870c71b00ebacd2e9134a8aa3f98a0052ab4b0e"}, + {file = "bcrypt-4.2.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:cb2a8ec2bc07d3553ccebf0746bbf3d19426d1c6d1adbd4fa48925f66af7b9e8"}, + {file = "bcrypt-4.2.0-cp39-abi3-win32.whl", hash = "sha256:77800b7147c9dc905db1cba26abe31e504d8247ac73580b4aa179f98e6608f34"}, + {file = "bcrypt-4.2.0-cp39-abi3-win_amd64.whl", hash = "sha256:61ed14326ee023917ecd093ee6ef422a72f3aec6f07e21ea5f10622b735538a9"}, + {file = "bcrypt-4.2.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:39e1d30c7233cfc54f5c3f2c825156fe044efdd3e0b9d309512cc514a263ec2a"}, + {file = "bcrypt-4.2.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f4f4acf526fcd1c34e7ce851147deedd4e26e6402369304220250598b26448db"}, + {file = "bcrypt-4.2.0.tar.gz", hash = "sha256:cf69eaf5185fd58f268f805b505ce31f9b9fc2d64b376642164e9244540c1221"}, +] + +[[package]] +name = "cffi" +version = "1.17.1" +requires_python = ">=3.8" +summary = "Foreign Function Interface for Python calling C code." +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +dependencies = [ + "pycparser", +] +files = [ + {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, + {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, + {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, + {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, + {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, + {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, + {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, + {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, +] + +[[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 = "(platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\") and sys_platform == \"win32\"" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "cryptography" +version = "43.0.3" +requires_python = ">=3.7" +summary = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +dependencies = [ + "cffi>=1.12; platform_python_implementation != \"PyPy\"", +] +files = [ + {file = "cryptography-43.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf7a1932ac4176486eab36a19ed4c0492da5d97123f1406cf15e41b05e787d2e"}, + {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63efa177ff54aec6e1c0aefaa1a241232dcd37413835a9b674b6e3f0ae2bfd3e"}, + {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e1ce50266f4f70bf41a2c6dc4358afadae90e2a1e5342d3c08883df1675374f"}, + {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:443c4a81bb10daed9a8f334365fe52542771f25aedaf889fd323a853ce7377d6"}, + {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:74f57f24754fe349223792466a709f8e0c093205ff0dca557af51072ff47ab18"}, + {file = "cryptography-43.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9762ea51a8fc2a88b70cf2995e5675b38d93bf36bd67d91721c309df184f49bd"}, + {file = "cryptography-43.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:81ef806b1fef6b06dcebad789f988d3b37ccaee225695cf3e07648eee0fc6b73"}, + {file = "cryptography-43.0.3-cp37-abi3-win32.whl", hash = "sha256:cbeb489927bd7af4aa98d4b261af9a5bc025bd87f0e3547e11584be9e9427be2"}, + {file = "cryptography-43.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:f46304d6f0c6ab8e52770addfa2fc41e6629495548862279641972b6215451cd"}, + {file = "cryptography-43.0.3-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:8ac43ae87929a5982f5948ceda07001ee5e83227fd69cf55b109144938d96984"}, + {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5"}, + {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4"}, + {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7"}, + {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405"}, + {file = "cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16"}, + {file = "cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73"}, + {file = "cryptography-43.0.3-cp39-abi3-win32.whl", hash = "sha256:d56e96520b1020449bbace2b78b603442e7e378a9b3bd68de65c782db1507995"}, + {file = "cryptography-43.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:0c580952eef9bf68c4747774cde7ec1d85a6e61de97281f2dba83c7d2c806362"}, + {file = "cryptography-43.0.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d03b5621a135bffecad2c73e9f4deb1a0f977b9a8ffe6f8e002bf6c9d07b918c"}, + {file = "cryptography-43.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a2a431ee15799d6db9fe80c82b055bae5a752bef645bba795e8e52687c69efe3"}, + {file = "cryptography-43.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:281c945d0e28c92ca5e5930664c1cefd85efe80e5c0d2bc58dd63383fda29f83"}, + {file = "cryptography-43.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f18c716be16bc1fea8e95def49edf46b82fccaa88587a45f8dc0ff6ab5d8e0a7"}, + {file = "cryptography-43.0.3.tar.gz", hash = "sha256:315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.2.2" +requires_python = ">=3.7" +summary = "Backport of PEP 654 (exception groups)" +groups = ["default"] +marker = "(platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\") and python_version < \"3.11\"" +files = [ + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, +] + +[[package]] +name = "flexcache" +version = "0.3" +requires_python = ">=3.9" +summary = "Saves and loads to the cache a transformed versions of a source object." +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +dependencies = [ + "typing-extensions", +] +files = [ + {file = "flexcache-0.3-py3-none-any.whl", hash = "sha256:d43c9fea82336af6e0115e308d9d33a185390b8346a017564611f1466dcd2e32"}, + {file = "flexcache-0.3.tar.gz", hash = "sha256:18743bd5a0621bfe2cf8d519e4c3bfdf57a269c15d1ced3fb4b64e0ff4600656"}, +] + +[[package]] +name = "flexparser" +version = "0.3.1" +requires_python = ">=3.9" +summary = "Parsing made fun ... using typing." +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +dependencies = [ + "typing-extensions", +] +files = [ + {file = "flexparser-0.3.1-py3-none-any.whl", hash = "sha256:2e3e2936bec1f9277f777ef77297522087d96adb09624d4fe4240fd56885c013"}, + {file = "flexparser-0.3.1.tar.gz", hash = "sha256:36f795d82e50f5c9ae2fde1c33f21f88922fdd67b7629550a3cc4d0b40a66856"}, +] + +[[package]] +name = "iniconfig" +version = "2.0.0" +requires_python = ">=3.7" +summary = "brain-dead simple config-ini parsing" +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "numpy" +version = "1.26.4" +requires_python = ">=3.9" +summary = "Fundamental package for array computing in Python" +groups = ["default"] +files = [ + {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, + {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"}, + {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"}, + {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"}, + {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"}, + {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"}, + {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"}, + {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"}, + {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, +] + +[[package]] +name = "packaging" +version = "23.2" +requires_python = ">=3.7" +summary = "Core utilities for Python packages" +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +files = [ + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, +] + +[[package]] +name = "paramiko" +version = "3.5.0" +requires_python = ">=3.6" +summary = "SSH2 protocol library" +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +dependencies = [ + "bcrypt>=3.2", + "cryptography>=3.3", + "pynacl>=1.5", +] +files = [ + {file = "paramiko-3.5.0-py3-none-any.whl", hash = "sha256:1fedf06b085359051cd7d0d270cebe19e755a8a921cc2ddbfa647fb0cd7d68f9"}, + {file = "paramiko-3.5.0.tar.gz", hash = "sha256:ad11e540da4f55cedda52931f1a3f812a8238a7af7f62a60de538cd80bb28124"}, +] + +[[package]] +name = "phoenix6" +version = "24.2.0" +requires_python = ">=3.7, <4" +summary = "Phoenix 6 Libraries" +groups = ["default"] +dependencies = [ + "setuptools", +] +files = [ + {file = "phoenix6-24.2.0-cp39-abi3-macosx_10_16_universal2.whl", hash = "sha256:5435ad068fbb66a7df1e12ce5ab91086b9c197fb50ac7a05fec6fa823d151ab0"}, + {file = "phoenix6-24.2.0-cp39-abi3-manylinux_2_35_aarch64.whl", hash = "sha256:72f994233822bd28db1939e18bf49d1c3b8497c179d3af1acb6af86fddaa9f89"}, + {file = "phoenix6-24.2.0-cp39-abi3-manylinux_2_35_armv7l.whl", hash = "sha256:31d5f492f5643bcb8808950145657db40966701de59d67792964c3f15f2982ff"}, + {file = "phoenix6-24.2.0-cp39-abi3-manylinux_2_35_x86_64.whl", hash = "sha256:060271c9df9d79317e2d58ad01f694979dc1375c2047148d87cf95d9b9f58424"}, + {file = "phoenix6-24.2.0-cp39-abi3-win_amd64.whl", hash = "sha256:7896b004f08733cfc9362d86b694a5d0d375b96a2f796ffd20cd62739b4dc97c"}, +] + +[[package]] +name = "photonlibpy" +version = "2024.3.1" +summary = "Pure-python implementation of PhotonLib for interfacing with PhotonVision on coprocessors." +groups = ["default"] +dependencies = [ + "pyntcore<2025,>=2024.0.0b2", + "robotpy-apriltag<2025,>=2024.0.0b2", + "robotpy-wpimath<2025,>=2024.0.0b2", + "wpilib<2025,>=2024.0.0b2", +] +files = [ + {file = "photonlibpy-2024.3.1-py3-none-any.whl", hash = "sha256:10b712f3cff9cff14dbc7b6676d236ebe1a690c446b5f9588c1790645258bfc1"}, + {file = "photonlibpy-2024.3.1.tar.gz", hash = "sha256:25543cf190977517ba303dec893bbab0f26f5d1cf63525c0e7d7f0124ba186d8"}, +] + +[[package]] +name = "pint" +version = "0.24.3" +requires_python = ">=3.9" +summary = "Physical quantities module" +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +dependencies = [ + "appdirs>=1.4.4", + "flexcache>=0.3", + "flexparser>=0.3", + "typing-extensions", +] +files = [ + {file = "Pint-0.24.3-py3-none-any.whl", hash = "sha256:d98667e46fd03a1b94694fbfa104ec30858684d8ab26952e2a348b48059089bb"}, + {file = "pint-0.24.3.tar.gz", hash = "sha256:d54771093e8b94c4e0a35ac638c2444ddf3ef685652bab7675ffecfa0c5c5cdf"}, +] + +[[package]] +name = "pluggy" +version = "1.5.0" +requires_python = ">=3.8" +summary = "plugin and hook calling mechanisms for python" +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +files = [ + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, +] + +[[package]] +name = "pycparser" +version = "2.22" +requires_python = ">=3.8" +summary = "C parser in Python" +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +files = [ + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, +] + +[[package]] +name = "pyfrc" +version = "2024.0.1" +requires_python = ">=3.8" +summary = "Development tools library for python interpreter used for the FIRST Robotics Competition" +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +dependencies = [ + "pint>=0.11.0", + "pytest-reraise", + "pytest>=3.9", + "robotpy-cli~=2024.0", + "wpilib<2025,>=2024.1.0", +] +files = [ + {file = "pyfrc-2024.0.1-py3-none-any.whl", hash = "sha256:2386be296bfb7e482a26c25e85ee61495ea10154f920d7450fec575defb8cc05"}, + {file = "pyfrc-2024.0.1.tar.gz", hash = "sha256:011076dbc62606b08eec6eb1bb30497d085d34cb71537a7ce0d06f44c8492855"}, +] + +[[package]] +name = "pynacl" +version = "1.5.0" +requires_python = ">=3.6" +summary = "Python binding to the Networking and Cryptography (NaCl) library" +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +dependencies = [ + "cffi>=1.4.1", +] +files = [ + {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"}, + {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"}, + {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"}, + {file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"}, + {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"}, + {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"}, +] + +[[package]] +name = "pynetconsole" +version = "2.0.4" +requires_python = ">=3.6" +summary = "A pure python implementation of a NetConsole listener" +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +files = [ + {file = "pynetconsole-2.0.4-py3-none-any.whl", hash = "sha256:3f6b51e3c943e900578ce92a85104d45784ea522863b025816cc7d580bd00069"}, + {file = "pynetconsole-2.0.4.tar.gz", hash = "sha256:a02a9a6538b63ab63ffb480a0e5c1485aa5f393da6a20f780a6b082c971762d5"}, +] + +[[package]] +name = "pyntcore" +version = "2024.3.2.0" +requires_python = ">=3.8" +summary = "Binary wrappers for the FRC ntcore library" +groups = ["default"] +dependencies = [ + "robotpy-wpinet==2024.3.2.0", + "robotpy-wpiutil==2024.3.2.0", +] +files = [ + {file = "pyntcore-2024.3.2.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:34c0e34f28eaeb9ef3e096ba49b4cc48a5e663ebf6578ce9595ab0851a73a1de"}, + {file = "pyntcore-2024.3.2.0-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:615c960729c49ca0dccfd4b598ac1809637e13efbdbb995ec35837101d8ba342"}, + {file = "pyntcore-2024.3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:7c3ab86b83761787887eec530bdfacd3fb21c8deaf9edcf03ca1c3d33d87eb5d"}, + {file = "pyntcore-2024.3.2.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:55050ced774f897fbe79063f2b3f460ee60df348c7cf5141784a6f07b2b59ca6"}, + {file = "pyntcore-2024.3.2.0-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:da4f8bb3d1428de15bf265fe21e70e17c221b620df069c6a30d59431d7f70357"}, + {file = "pyntcore-2024.3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:355e6fc18b8a2bd2b3fb6467428f42bde1615444d2dc9ee96bbeb4ad8a5d0936"}, + {file = "pyntcore-2024.3.2.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:14d31540c29cdbc6bfbfc81b9b3e1535b91aec03bf012e42bb388a9ee450cca2"}, + {file = "pyntcore-2024.3.2.0-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:5f805578f476b725e32a8250af8bb953f526c1fa742e851d258757229cce07c8"}, + {file = "pyntcore-2024.3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:f4689b90e35b0630ca35b0803d7d2b4e993d9cc13073dc11e49c0823be5570fb"}, +] + +[[package]] +name = "pytest" +version = "8.3.3" +requires_python = ">=3.8" +summary = "pytest: simple powerful testing with Python" +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +dependencies = [ + "colorama; sys_platform == \"win32\"", + "exceptiongroup>=1.0.0rc8; python_version < \"3.11\"", + "iniconfig", + "packaging", + "pluggy<2,>=1.5", + "tomli>=1; python_version < \"3.11\"", +] +files = [ + {file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"}, + {file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"}, +] + +[[package]] +name = "pytest-reraise" +version = "2.1.2" +requires_python = ">=3.6.1,<4.0.0" +summary = "Make multi-threaded pytest test cases fail when they should" +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +dependencies = [ + "pytest>=4.6", +] +files = [ + {file = "pytest-reraise-2.1.2.tar.gz", hash = "sha256:5ab59bd0e2028be095289e6dfc9e36cc0b56936465278f3223e81bea0f2d1c70"}, + {file = "pytest_reraise-2.1.2-py3-none-any.whl", hash = "sha256:c22430d33b2cc18905959d7af28978e371113fcc6ef67b5fec95efcd80b88c16"}, +] + +[[package]] +name = "robotpy" +version = "2024.3.2.1" +requires_python = ">=3.8,<3.13" +summary = "Meta package to make installing robotpy easier" +groups = ["default"] +dependencies = [ + "pyfrc<2025.0.0,>=2024.0.0; platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"", + "pyntcore==2024.3.2.0", + "robotpy-cli<2025.0.0,>=2024.0.0", + "robotpy-hal==2024.3.2.0", + "robotpy-halsim-gui==2024.3.2.0; platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"", + "robotpy-installer<2025.0.0,>=2024.2.0; platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"", + "robotpy-wpilib-utilities<2025.0.0,>=2024.0.0", + "robotpy-wpimath==2024.3.2.0", + "robotpy-wpinet==2024.3.2.0", + "robotpy-wpiutil==2024.3.2.0", + "wpilib==2024.3.2.0", +] +files = [ + {file = "robotpy-2024.3.2.1-py3-none-any.whl", hash = "sha256:ac4de7f1074f7a1483cd7ec7ee965408762bcbff7ab24df5001c4c5ed261be3d"}, + {file = "robotpy-2024.3.2.1.tar.gz", hash = "sha256:8fa2d54a94182d3fda8cf12df928d48237598d6c2e1624e0803a0589ce74c4cd"}, +] + +[[package]] +name = "robotpy-apriltag" +version = "2024.3.2.0" +requires_python = ">=3.8" +summary = "RobotPy bindings for WPILib's AprilTag library" +groups = ["default"] +dependencies = [ + "robotpy-wpimath==2024.3.2.0", + "robotpy-wpiutil==2024.3.2.0", +] +files = [ + {file = "robotpy_apriltag-2024.3.2.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:af969bf6ccfc0521ea90e12102598e3019036e44daae18b41ff38757163276d6"}, + {file = "robotpy_apriltag-2024.3.2.0-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:70deb648eab7a254899cc1e64f4686dd86d980499817f42decf139db0259ff68"}, + {file = "robotpy_apriltag-2024.3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:b73305c2fb6f39ec69f80cc86e4974084e958962e6ac471a0fde882bb6ec28c2"}, + {file = "robotpy_apriltag-2024.3.2.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:e3eaf91581758a4a221e39bc46b4d6a003f6b02cad8f606745273a33b5c6129e"}, + {file = "robotpy_apriltag-2024.3.2.0-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:91b18209e9978f5e6758dfea35ad67cb3946f8ea8b368addc58226df5c02bacf"}, + {file = "robotpy_apriltag-2024.3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:04b7b8d6384918c2fdaec740d979364d2adc764ed9787ca47a1ee54bcfb59b7e"}, + {file = "robotpy_apriltag-2024.3.2.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:df975a0a71bd3d6cac944aabd60992154c3c4452c5b1e5f6d4afaae2895ccddd"}, + {file = "robotpy_apriltag-2024.3.2.0-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:4ec49df16cb4de11755a54cde8a67737417f072e0f3db5ea6d3a527fc17a86bc"}, + {file = "robotpy_apriltag-2024.3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:0186d09e7b39d45e5c408a62a191ecafc22e8d9fe23be49ab5ec9f04acd72d23"}, +] + +[[package]] +name = "robotpy-cli" +version = "2024.0.0" +requires_python = ">=3.8" +summary = "" +groups = ["default"] +files = [ + {file = "robotpy-cli-2024.0.0.tar.gz", hash = "sha256:e6519f06856eb0a7ef5f25a57bfc8dcb20635cef84706fb37c0b602d59e33f39"}, + {file = "robotpy_cli-2024.0.0-py3-none-any.whl", hash = "sha256:9284035fa67058b33593b1846e13501eda0861fb9d9adce4bd01b101c9f1f26e"}, +] + +[[package]] +name = "robotpy-hal" +version = "2024.3.2.0" +requires_python = ">=3.8" +summary = "Binary wrapper for FRC HAL" +groups = ["default"] +dependencies = [ + "robotpy-wpiutil==2024.3.2.0", +] +files = [ + {file = "robotpy_hal-2024.3.2.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7f502f2e63afa843e58cff9ca122db715fd5cf5bb2d7b1af560eaa74594de3a9"}, + {file = "robotpy_hal-2024.3.2.0-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:f6da11a7e1619fa591cca78dfd866aaa5f46e03e7436c98f5ef98d71eaa97562"}, + {file = "robotpy_hal-2024.3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:2132d8fc81dce244191759333d4be8ac1143c5a2b5654a2bc877fee4f7a18b5e"}, + {file = "robotpy_hal-2024.3.2.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:4e4b605c219647402733e66532a142f2e71e37b78e3507cfb9e7c031eb5ffa0a"}, + {file = "robotpy_hal-2024.3.2.0-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:6367540610d4398bb6d81922d540c2665115e3167d9c263b4fb2aaf7364f4c5a"}, + {file = "robotpy_hal-2024.3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:f82d2ae057d86a59c4379f67b43fa304d999e90f6b3f84ff877abc16844d7d0e"}, + {file = "robotpy_hal-2024.3.2.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:714fb5b73eaf758b69a8a506f6ede60ca16d4036014eae383b2493f885d6cfd7"}, + {file = "robotpy_hal-2024.3.2.0-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:e02088620b2809000c85e2f8da9a6cc7a58592e5fa81b9b75d33e83e5dce8d2f"}, + {file = "robotpy_hal-2024.3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:8da8365f09e7cb2287d9b50e8ebe1a117f47f1cf7cf2c4ebe75146b4d6ec7189"}, +] + +[[package]] +name = "robotpy-halsim-gui" +version = "2024.3.2.0" +requires_python = ">=3.8" +summary = "WPILib command framework" +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +dependencies = [ + "pyntcore==2024.3.2.0", + "robotpy-hal==2024.3.2.0", + "robotpy-wpimath==2024.3.2.0", + "robotpy-wpiutil==2024.3.2.0", +] +files = [ + {file = "robotpy_halsim_gui-2024.3.2.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:ad048ce936c732c031600e41d19eac23f541ee5021f72daaf89a74e00c5b1ff7"}, + {file = "robotpy_halsim_gui-2024.3.2.0-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:ef94a2d1261aaa24cd6c74ac5a301b4b11ee377adeac8eebbf0a0a3dbadd8d2d"}, + {file = "robotpy_halsim_gui-2024.3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:50d8d8e576f24ebed2090824fbb48f5b1be7d435af78f907fe9f2ef8bbd63b32"}, + {file = "robotpy_halsim_gui-2024.3.2.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:009a81a524cbfa0e7de0756b1eeb50d64f908e16991c60507dd2b1c2feb20c2f"}, + {file = "robotpy_halsim_gui-2024.3.2.0-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:63a3a4926af23d1f3f9224490ffed605dca86ccf14294906871ff847d15c3c68"}, + {file = "robotpy_halsim_gui-2024.3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:2006162cb96fda821c5f94679168374de2fbeeb3d61150dda6cfe5ab33bb17e5"}, + {file = "robotpy_halsim_gui-2024.3.2.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:27ecfc05f54d48ecf228198daa6fb02ef9589d42efe08f40bd557d3066e1dc43"}, + {file = "robotpy_halsim_gui-2024.3.2.0-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:27804d6a0c32caafb9db82311e6b56fe9699b67e12fdcbdee921124a7b080c0a"}, + {file = "robotpy_halsim_gui-2024.3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:5d9f700239ef755da05d71910dc04daec74ac7cc11e61bd38b07ae02b382c24b"}, +] + +[[package]] +name = "robotpy-installer" +version = "2024.2.2" +requires_python = ">=3.8" +summary = "Installation utility program for RobotPy" +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +dependencies = [ + "packaging~=23.2", + "paramiko", + "pynetconsole~=2.0.2", + "robotpy-cli~=2024.0", + "tomli", + "tomlkit", +] +files = [ + {file = "robotpy-installer-2024.2.2.tar.gz", hash = "sha256:12e243acd6b956f80f7985e40ea8b331819ff4d6324a7c541b7045ac32678087"}, + {file = "robotpy_installer-2024.2.2-py3-none-any.whl", hash = "sha256:510cc4c7cc11b0fd248604d7dd7eb366b9018b53b9cb36c06306e762c92bfea7"}, +] + +[[package]] +name = "robotpy-navx" +version = "2024.1.1" +requires_python = ">=3.8" +summary = "Python wrapper for KauaiLabs NavX sensor" +groups = ["default"] +dependencies = [ + "robotpy-wpimath<2025.0.0,>=2024.3.2", + "robotpy-wpiutil<2025.0.0,>=2024.3.2", + "wpilib<2025.0.0,>=2024.3.2", +] +files = [ + {file = "robotpy-navx-2024.1.1.tar.gz", hash = "sha256:8f7134e8e514577e8a5ae388907d51fb7826a7b6d6018dabd81eecd562ed0389"}, + {file = "robotpy_navx-2024.1.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:ab9259f35c31f469e601beefa7883d8e6202aa6c61b7e4a04464d97bef7cdadc"}, + {file = "robotpy_navx-2024.1.1-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:91bff8bb75954ad8311732ee64611db82eeb56c7f455a48c6913bf086caac35d"}, + {file = "robotpy_navx-2024.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:6713c4c250312f7bb02c8a07995a326a70a1d32b8d57705776966298f078f31b"}, + {file = "robotpy_navx-2024.1.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:ed3ac489cf8cd42e5805098034636482aa7079ca7aa65783d8b9bc50874484d2"}, + {file = "robotpy_navx-2024.1.1-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:ca26b7140675e5411c7457adf5df3e52c9d7a660714e0d8d75d5b8939db09b7a"}, + {file = "robotpy_navx-2024.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:f4b833183e123310ba2835ff6115f819074d1cfd566688355248f02cca8ed43c"}, + {file = "robotpy_navx-2024.1.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:fca811dff6a8815af116af614a8cc50189bf60d99ba9e580bc4d1eda6445ae8d"}, + {file = "robotpy_navx-2024.1.1-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:08d3f05ed97b532367b8feca5b47e46c874570f9bb8402aa3a54ba041c4409d5"}, + {file = "robotpy_navx-2024.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:d8ad75baafae83e0bb7667e1eb1f947a89cd6c750466d72eb27fc012d2444a55"}, +] + +[[package]] +name = "robotpy-rev" +version = "2024.2.4" +requires_python = ">=3.8" +summary = "REVLib for RobotPy" +groups = ["default"] +dependencies = [ + "robotpy-wpimath<2025.0.0,>=2024.3.2", + "robotpy-wpiutil<2025.0.0,>=2024.3.2", + "wpilib<2025.0.0,>=2024.3.2", +] +files = [ + {file = "robotpy-rev-2024.2.4.tar.gz", hash = "sha256:890c894172d13175c0bf3a882588a3c8da972cfc04917c8ee6a40f07497368c6"}, + {file = "robotpy_rev-2024.2.4-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:b9e261c96a6fe10d93b623bccde5dbefb1dfb53b00e2bfed29591601e4d2ed30"}, + {file = "robotpy_rev-2024.2.4-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:2bd6d0a71d5737915ba10eccd3fede62d61c0d9ed65e6c8baa84aed1d96b6550"}, + {file = "robotpy_rev-2024.2.4-cp310-cp310-win_amd64.whl", hash = "sha256:d51490f0b4a07645d2edea72204a8a2bad2e5ec88705d0615b0de01eda28926b"}, + {file = "robotpy_rev-2024.2.4-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:03db134b567ab128b28d62f2e62a3e8042b158bdd792e02173e4a5f7fb88a6f0"}, + {file = "robotpy_rev-2024.2.4-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:8dddb16f92055755841c2b1c8e063364f3606daf4d34b1e92dff2903f0efc0f6"}, + {file = "robotpy_rev-2024.2.4-cp311-cp311-win_amd64.whl", hash = "sha256:87b023e1f9be8b3ea53151a59ebbad9d07136bcb76aa4ecd1bebb5044e57ec76"}, + {file = "robotpy_rev-2024.2.4-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:91cb9d43295e85ce2f5e554e631c150cc0d14a75922cf3c5936933df9f90c15e"}, + {file = "robotpy_rev-2024.2.4-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:7323042f94a68556b5dc5c9a2fc1a74948d10ddddfabbf01d74f1f99d9c4e7d9"}, + {file = "robotpy_rev-2024.2.4-cp312-cp312-win_amd64.whl", hash = "sha256:c44b2abbd2092056b24753f1f46d229c51d2879046f1782a02bb00d51275218b"}, +] + +[[package]] +name = "robotpy-wpilib-utilities" +version = "2024.0.0" +requires_python = ">=3.8" +summary = "Useful utility functions/objects for RobotPy" +groups = ["default"] +dependencies = [ + "wpilib<2025,>=2024.1.1.0", +] +files = [ + {file = "robotpy-wpilib-utilities-2024.0.0.tar.gz", hash = "sha256:f2e7e512e3e9ad938893175b22c827f97d0866ade47f34c25d68622c3f8a4c3a"}, + {file = "robotpy_wpilib_utilities-2024.0.0-py3-none-any.whl", hash = "sha256:da0d3495d28b8f758c0bc12f1075996273aae831c5dd9d85d6b0581f8f08bcaa"}, +] + +[[package]] +name = "robotpy-wpimath" +version = "2024.3.2.0" +requires_python = ">=3.8" +summary = "Binary wrapper for FRC WPIMath library" +groups = ["default"] +dependencies = [ + "robotpy-wpiutil==2024.3.2.0", +] +files = [ + {file = "robotpy_wpimath-2024.3.2.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:b2d5f852c734b53fab279532a0ac47cb9570036208543a01cbd10aeb3a73fa70"}, + {file = "robotpy_wpimath-2024.3.2.0-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:e7b3b8759d1c791c95f8a62199f4038c4c485b85e0cb160d4c93120591795269"}, + {file = "robotpy_wpimath-2024.3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:6813e4a22b9463410eb5bcd7c838a04ef1fd59c3590ef21176c7c1d7c74bb5cc"}, + {file = "robotpy_wpimath-2024.3.2.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:e2b2670939545b80afd85692031e86f2a53da5b5ecdf97baaa96cb687067294f"}, + {file = "robotpy_wpimath-2024.3.2.0-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:0844991c6c84747f32274628d3eb15f7082458090fed015fe4f7dbd08fcbdb4c"}, + {file = "robotpy_wpimath-2024.3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:fbc80e929cba60d25208d167f573a1151a8f8851a66a670fe464ef0c53fee76a"}, + {file = "robotpy_wpimath-2024.3.2.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:2f0c4168f128bef603b55cf926cedad27eed0a98824a4fe244de51db48e0d05d"}, + {file = "robotpy_wpimath-2024.3.2.0-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:a474951a3dcf80154aad597d46eb26de7e485145228e8e2892a0adc3cc98e3fd"}, + {file = "robotpy_wpimath-2024.3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:abd2a365a5edd9f6caca56540a48256549cedef490f3286274443fd9a8f703e6"}, +] + +[[package]] +name = "robotpy-wpinet" +version = "2024.3.2.0" +requires_python = ">=3.8" +summary = "Binary wrapper for FRC wpinet library" +groups = ["default"] +dependencies = [ + "robotpy-wpiutil==2024.3.2.0", +] +files = [ + {file = "robotpy_wpinet-2024.3.2.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:132906e671d3bb1e1775817ecf3fa375e8f95a2ad11288ad7fec8a3b47c21685"}, + {file = "robotpy_wpinet-2024.3.2.0-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:05f52054c46f41e1f5e98601cb9699e5975874b5fd8a7b65bf21437a10df262c"}, + {file = "robotpy_wpinet-2024.3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:64a0cbbe5cb9e043e06f66e9388cff1a3f057f4150232629e93ab7b71c4366ff"}, + {file = "robotpy_wpinet-2024.3.2.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:93de7c9fe78fb095c8f83921c1a37b3ab045e7108b0951b45802f1e6690db8bb"}, + {file = "robotpy_wpinet-2024.3.2.0-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:844fae2241f60b9ed53bbc292f2e36ae513f9bb2c30b46a7a7547ab257a3c40c"}, + {file = "robotpy_wpinet-2024.3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:61536f024ab59a4ad56cb88608708188590b90307436eef87dda465ddf59553e"}, + {file = "robotpy_wpinet-2024.3.2.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:45f5e0459f41b8ff5bd1c323fb3d969bddfdaf7d34f36c995d57e7216743a882"}, + {file = "robotpy_wpinet-2024.3.2.0-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:92a5e27678065adc4d0ff008527772fd58d5e31ccf57a77d2a899219be8193eb"}, + {file = "robotpy_wpinet-2024.3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:802e398e55a5c9e1f7a60b425b169b2acb08c0c5d45dcd34e6bb5a1253455094"}, +] + +[[package]] +name = "robotpy-wpiutil" +version = "2024.3.2.0" +requires_python = ">=3.8" +summary = "Binary wrapper for FRC WPIUtil library" +groups = ["default"] +files = [ + {file = "robotpy_wpiutil-2024.3.2.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:bf115575d856695481d07d397d3a12e035e71b2b1cbcaac89a8b66b2e855da05"}, + {file = "robotpy_wpiutil-2024.3.2.0-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:f007c94290cebffae26df1ed883e6e7b4320974e99e665561bce8db5ebf1230b"}, + {file = "robotpy_wpiutil-2024.3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:0780127251fbce6542a67951e517b0c453153d53b42480e678cc9182e9879674"}, + {file = "robotpy_wpiutil-2024.3.2.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:ccf9f3fbc0e4ea3e7d645bfab9dd5c1f2de7c8f5a01a75d6bd2c37f534e2e855"}, + {file = "robotpy_wpiutil-2024.3.2.0-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:f3cbbe94443018dccf471b57c270823544c923d2b10b374b6e74e935153baf86"}, + {file = "robotpy_wpiutil-2024.3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:b83f70b378817de29f122f8e5014f612bd72eb83c01e1d37065334e682e8a967"}, + {file = "robotpy_wpiutil-2024.3.2.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:e7c909fcf28e3d94f70adce57f897e47320edf5bcc45aa3956ce736bd6bc50cc"}, + {file = "robotpy_wpiutil-2024.3.2.0-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:ab5c4b9a06f462200fc67d7aaa0854b227c98be9d4bfbdfb929d787b72642a88"}, + {file = "robotpy_wpiutil-2024.3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:4972f2acfae01c0290c057031918dc9bd8c62f6b5c60addaccb2f3e6ad1d3dd0"}, +] + +[[package]] +name = "setuptools" +version = "75.2.0" +requires_python = ">=3.8" +summary = "Easily download, build, install, upgrade, and uninstall Python packages" +groups = ["default"] +files = [ + {file = "setuptools-75.2.0-py3-none-any.whl", hash = "sha256:a7fcb66f68b4d9e8e66b42f9876150a3371558f98fa32222ffaa5bced76406f8"}, + {file = "setuptools-75.2.0.tar.gz", hash = "sha256:753bb6ebf1f465a1912e19ed1d41f403a79173a9acf66a42e7e6aec45c3c16ec"}, +] + +[[package]] +name = "tomli" +version = "2.0.2" +requires_python = ">=3.8" +summary = "A lil' TOML parser" +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +files = [ + {file = "tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38"}, + {file = "tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"}, +] + +[[package]] +name = "tomlkit" +version = "0.13.2" +requires_python = ">=3.8" +summary = "Style preserving TOML library" +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +files = [ + {file = "tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde"}, + {file = "tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79"}, +] + +[[package]] +name = "typing-extensions" +version = "4.12.2" +requires_python = ">=3.8" +summary = "Backported and Experimental Type Hints for Python 3.8+" +groups = ["default"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +files = [ + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, +] + +[[package]] +name = "wpilib" +version = "2024.3.2.0" +requires_python = ">=3.8" +summary = "Binary wrapper for FRC WPILib" +groups = ["default"] +dependencies = [ + "pyntcore==2024.3.2.0", + "robotpy-cli~=2024.0b", + "robotpy-hal==2024.3.2.0", + "robotpy-wpimath==2024.3.2.0", + "robotpy-wpiutil==2024.3.2.0", +] +files = [ + {file = "wpilib-2024.3.2.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:0703d5e4f3f1be08bd2aac3324894ea3983be0c20b6f3fdd9949ffbd9b12f4bd"}, + {file = "wpilib-2024.3.2.0-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:2c596589a7be0d10374a5ad4e652495214df4a7e7e24536dfb43dc1312ccfc7f"}, + {file = "wpilib-2024.3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:fa7e3534533097da5de558b4e457c5e1e9a7f4ca3d1d3aa4b9b28b127b1cc85c"}, + {file = "wpilib-2024.3.2.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:c1b71d890a6696d89fef865651f1d1db2fcd9160829bc94210d95bbc6f821651"}, + {file = "wpilib-2024.3.2.0-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:d00e32ebaf7b256507c6852fda37ddd7cf66ce0759304c66596b71d8888aad93"}, + {file = "wpilib-2024.3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:957a6737075dbcc185506e1f235ec647e67a309cb5f44a52e0106062f6d5b5a8"}, + {file = "wpilib-2024.3.2.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:fcc7abfef7a5961bc3a5f3846c74a3c9a951879f0dec53084e2757e54e70b0c7"}, + {file = "wpilib-2024.3.2.0-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:70d9f5ab97cf604e144e9e4e782306cca41b90869da0ae598f01d5b6fa88b11d"}, + {file = "wpilib-2024.3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:09eae37ee6dfcfa116f4fcf7c43a86e7ac4c4e8d1a3070fb67f8ab56862386d0"}, +] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..1260f854 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,91 @@ +[tool.coverage.run] +branch = true + +[tool.coverage.report] +exclude_lines = [ + "pragma: no cover", + "raise NotImplementedError", + "if __name__ == .__main__.:", + "if typing.TYPE_CHECKING:", +] + +[tool.mypy] +check_untyped_defs = true +warn_redundant_casts = true +warn_unused_ignores = true +warn_unreachable = true +strict_equality = true + +[[tool.mypy.overrides]] +module = "photonlibpy.*" +# https://github.com/PhotonVision/photonvision/issues/1210 +ignore_missing_imports = true + +[tool.pytest.ini_options] +addopts = "--strict-markers -v --maxfail=2" +pythonpath = "." +testpaths = ["tests"] +xfail_strict = true + +[tool.ruff] +target-version = "py39" + +[tool.ruff.lint] +select = [ + # pycodestyle + "E", + # pyflakes + "F", + # flake8-bugbear + "B", + # pyupgrade + "UP", + # flake8-comprehensions + "C4", + # flake8-logging-format + "G", + # flake8-simplify + "SIM", + # flake8-print + "T20", + # perflint + "PERF", +] +ignore = ["E501"] + + +[tool.pdm] +[project] +name = "pyreefscape" +version = "0.0.0" +description = "The Drop Bears' FRC 2025 robot code" +authors = [ + {name = "The Drop Bears", email = "enquiries@thedropbears.org.au"}, +] +readme = "README.md" +license = {text = "MIT"} +requires-python = ">=3.10,<3.13" + +dependencies = [ + "numpy~=1.25", + "phoenix6~=24.2.0", + # robotpy[apriltag] pins numpy to a version that doesn't build cleanly on Python 3.12. + "robotpy==2024.3.2.1", + "robotpy-apriltag~=2024.3.2", + "robotpy-navx==2024.1.1", + "robotpy-rev~=2024.2.4", + "robotpy-wpilib-utilities==2024.0.0", + "photonlibpy==2024.3.1", +] + +[tool.robotpy] +requires = [ + "numpy~=1.25", + "phoenix6~=24.2.0", + "robotpy-navx==2024.1.1", + "robotpy-rev~=2024.2.4", + "robotpy-wpilib-utilities==2024.0.0", + "photonlibpy==2024.3.1", +] +robotpy_version = "2024.3.2.1" +robotpy_extras = ["apriltag"] From b9fd5a61636545874b9a6cddde35182388e26054 Mon Sep 17 00:00:00 2001 From: Beana1234 Date: Tue, 22 Oct 2024 19:11:15 +1100 Subject: [PATCH 02/20] add ignore file --- .gitignore | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..a1e297bc --- /dev/null +++ b/.gitignore @@ -0,0 +1,67 @@ +### Python ### +__pycache__/ + +# Unit test / coverage reports +htmlcov/ +.coverage +.coverage.* +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# pyenv +.python-version + +# pdm +.pdm-python +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Rope project settings +.ropeproject + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre +.pyre/ + +# pytype static type analyzer +.pytype/ + +### macOS ### +*.DS_Store +.AppleDouble +.LSOverride + +# Thumbnails +._* + +### VS Code ### +.vscode/* +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +### WPILib ### +networktables.json +simgui*.json +logs/ +ctre_sim/ From 5699a892363bf502b0ab4d84a6b8c5f809ee19e9 Mon Sep 17 00:00:00 2001 From: Beana1234 Date: Tue, 22 Oct 2024 19:12:19 +1100 Subject: [PATCH 03/20] enable pre-commit functionality --- .pre-commit-config.yaml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..c72bceb5 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,32 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +ci: + autofix_prs: false + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + # Side effects + - id: fix-byte-order-marker + - id: trailing-whitespace + - id: end-of-file-fixer + - id: mixed-line-ending + # Non-modifying checks + - id: check-added-large-files + - id: check-case-conflict + - id: check-merge-conflict + - id: check-toml + - id: check-yaml + + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.4.4 + hooks: + - id: ruff + args: + - "--fix" + + - repo: https://github.com/psf/black-pre-commit-mirror + rev: 24.4.2 + hooks: + - id: black From 233f9f345e83302cc70e4456eb2e6fb5301f3c80 Mon Sep 17 00:00:00 2001 From: Beana1234 Date: Tue, 22 Oct 2024 19:14:49 +1100 Subject: [PATCH 04/20] add team number for deployment --- .wpilib/wpilib_preferences.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .wpilib/wpilib_preferences.json diff --git a/.wpilib/wpilib_preferences.json b/.wpilib/wpilib_preferences.json new file mode 100644 index 00000000..381f2871 --- /dev/null +++ b/.wpilib/wpilib_preferences.json @@ -0,0 +1,3 @@ +{ + "teamNumber": 4774 +} From 72035aa259dbe4b81846d99d5a2652aa05f53b85 Mon Sep 17 00:00:00 2001 From: Beana1234 Date: Tue, 22 Oct 2024 19:19:59 +1100 Subject: [PATCH 05/20] add ci --- .github/workflows/ci.yml | 47 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..9dfefdd9 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,47 @@ +name: CI + +on: + push: + branches: + - main + pull_request: + merge_group: + +jobs: + test: + runs-on: ubuntu-latest + permissions: + id-token: write + + steps: + - uses: actions/checkout@v4 + - uses: pdm-project/setup-pdm@v4 + with: + cache: true + - name: Install dependencies + run: | + pdm install + pdm run python -m ensurepip + pdm run python -m pip install coverage pytest-github-actions-annotate-failures + - run: pdm run robotpy coverage test + - run: pdm run coverage xml + - uses: codecov/codecov-action@v4 + with: + use_oidc: true + + mypy: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: pdm-project/setup-pdm@v4 + with: + cache: true + - name: Install dependencies + run: | + pdm install + - name: mypy + uses: liskin/gh-problem-matcher-wrap@v3 + with: + linters: mypy + run: pdm run mypy --show-column-numbers . From 1f0a36edee706b8c88cea574340261a3ef1af87e Mon Sep 17 00:00:00 2001 From: Beana1234 Date: Tue, 22 Oct 2024 19:26:25 +1100 Subject: [PATCH 06/20] add vscode functionality --- .vscode/extensions.json | 5 +++++ .vscode/launch.json | 39 ++++++++++++++++++++++++++++++++++ .vscode/tasks.json | 47 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..5d21c814 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "charliermarsh.ruff" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..fef20a1c --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,39 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "RobotPy: Simulate", + "type": "python", + "request": "launch", + "module": "robotpy", + "args": [ + "sim" + ] + }, + { + "name": "RobotPy: Test", + "type": "python", + "request": "launch", + "module": "robotpy", + "args": [ + "test" + ] + }, + { + "name": "Python: Attach to roboRIO", + "type": "python", + "request": "attach", + "port": 5678, + "host": "10.47.74.2", + "pathMappings": [ + { + "localRoot": "${workspaceFolder}", + "remoteRoot": "." + } + ] + } + ] +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..538a127f --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,47 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "deploy with netconsole", + "type": "process", + "group": "build", + "command": "${command:python.interpreterPath}", + "args": [ + "-m", + "robotpy", + "deploy", + "--nc" + ] + }, + { + "label": "deploy", + "type": "process", + "group":{ + "kind": "build", + "isDefault": true + }, + "command": "${command:python.interpreterPath}", + "args": [ + "-m", + "robotpy", + "deploy" + ] + }, + { + "label": "test", + "type": "process", + "group": { + "kind": "test", + "isDefault": true + }, + "command": "${command:python.interpreterPath}", + "args": [ + "-m", + "robotpy", + "test" + ] + } + ] +} From 7622898fe57f86de387d88f460624b61d3fb83dd Mon Sep 17 00:00:00 2001 From: Beana1234 Date: Tue, 22 Oct 2024 19:30:40 +1100 Subject: [PATCH 07/20] move components into components folder --- chassis.py => components/chassis.py | 966 ++++++++++++++-------------- vision.py => components/vision.py | 384 +++++------ 2 files changed, 675 insertions(+), 675 deletions(-) rename chassis.py => components/chassis.py (97%) rename vision.py => components/vision.py (97%) diff --git a/chassis.py b/components/chassis.py similarity index 97% rename from chassis.py rename to components/chassis.py index 62307e57..27dd0bff 100644 --- a/chassis.py +++ b/components/chassis.py @@ -1,483 +1,483 @@ -from logging import Logger -import math - -from phoenix6.hardware import TalonFX, CANcoder -from phoenix6.controls import VoltageOut, VelocityVoltage, PositionDutyCycle -from phoenix6.signals import InvertedValue, NeutralModeValue -from phoenix6.configs import ( - ClosedLoopGeneralConfigs, - MotorOutputConfigs, - FeedbackConfigs, - Slot0Configs, -) -import magicbot -import navx -import ntcore -import wpilib -from wpimath.kinematics import ( - SwerveDrive4Kinematics, - ChassisSpeeds, - SwerveModuleState, - SwerveModulePosition, -) -from wpimath.geometry import Translation2d, Rotation2d, Pose2d -from wpimath.estimator import SwerveDrive4PoseEstimator -from wpimath.controller import SimpleMotorFeedforwardMeters -from wpimath.trajectory import TrapezoidProfileRadians -from wpimath.controller import ProfiledPIDControllerRadians - -from magicbot import feedback - -from utilities.functions import rate_limit_module -from utilities.game import is_red -from utilities.ctre import FALCON_FREE_RPS -from utilities.position import TeamPoses -from ids import CancoderIds, TalonIds - - -class SwerveModule: - DRIVE_GEAR_RATIO = (14.0 / 50.0) * (25.0 / 19.0) * (15.0 / 45.0) - STEER_GEAR_RATIO = (14 / 50) * (10 / 60) - WHEEL_CIRCUMFERENCE = 4 * 2.54 / 100 * math.pi - - DRIVE_MOTOR_REV_TO_METRES = WHEEL_CIRCUMFERENCE * DRIVE_GEAR_RATIO - STEER_MOTOR_REV_TO_RAD = math.tau * STEER_GEAR_RATIO - - # limit the acceleration of the commanded speeds of the robot to what is actually - # achiveable without the wheels slipping. This is done to improve odometry - accel_limit = 15 # m/s^2 - - def __init__( - self, - x: float, - y: float, - drive_id: int, - steer_id: int, - encoder_id: int, - *, - drive_reversed: bool = False, - ): - """ - x, y: where the module is relative to the center of the robot - *_id: can ids of steer and drive motors and absolute encoder - """ - self.translation = Translation2d(x, y) - self.state = SwerveModuleState(0, Rotation2d(0)) - self.do_smooth = True - - # Create Motor and encoder objects - self.steer = TalonFX(steer_id) - self.drive = TalonFX(drive_id) - self.drive_id = drive_id - self.encoder = CANcoder(encoder_id) - - # Reduce CAN status frame rates before configuring - self.steer.get_fault_field().set_update_frequency( - frequency_hz=4, timeout_seconds=0.01 - ) - self.drive.get_fault_field().set_update_frequency( - frequency_hz=4, timeout_seconds=0.01 - ) - - # Configure steer motor - steer_config = self.steer.configurator - - steer_motor_config = MotorOutputConfigs() - steer_motor_config.neutral_mode = NeutralModeValue.BRAKE - # The SDS Mk4i rotation has one pair of gears. - steer_motor_config.inverted = InvertedValue.CLOCKWISE_POSITIVE - - steer_gear_ratio_config = FeedbackConfigs().with_sensor_to_mechanism_ratio( - 1 / self.STEER_GEAR_RATIO - ) - - # configuration for motor pid - steer_pid = Slot0Configs().with_k_p(2.4206).with_k_i(0).with_k_d(0.060654) - steer_closed_loop_config = ClosedLoopGeneralConfigs() - steer_closed_loop_config.continuous_wrap = True - - steer_config.apply(steer_motor_config) - steer_config.apply(steer_pid, 0.01) - steer_config.apply(steer_gear_ratio_config) - steer_config.apply(steer_closed_loop_config) - - # Configure drive motor - drive_config = self.drive.configurator - - drive_motor_config = MotorOutputConfigs() - drive_motor_config.neutral_mode = NeutralModeValue.BRAKE - drive_motor_config.inverted = ( - InvertedValue.CLOCKWISE_POSITIVE - if drive_reversed - else InvertedValue.COUNTER_CLOCKWISE_POSITIVE - ) - - drive_gear_ratio_config = FeedbackConfigs().with_sensor_to_mechanism_ratio( - 1 / self.DRIVE_MOTOR_REV_TO_METRES - ) - - # configuration for motor pid and feedforward - self.drive_pid = Slot0Configs().with_k_p(1.0868).with_k_i(0).with_k_d(0) - self.drive_ff = SimpleMotorFeedforwardMeters(kS=0.15172, kV=2.8305, kA=0.082659) - - drive_config.apply(drive_motor_config) - drive_config.apply(self.drive_pid, 0.01) - drive_config.apply(drive_gear_ratio_config) - - self.central_angle = Rotation2d(x, y) - self.module_locked = False - - self.sync_steer_encoder() - - self.drive_request = VelocityVoltage(0) - self.stop_request = VoltageOut(0) - - def get_angle_absolute(self) -> float: - """Gets steer angle (rot) from absolute encoder""" - return self.encoder.get_absolute_position().value - - def get_angle_integrated(self) -> float: - """Gets steer angle from motor's integrated relative encoder""" - return self.steer.get_position().value * math.tau - - def get_rotation(self) -> Rotation2d: - """Get the steer angle as a Rotation2d""" - return Rotation2d(self.get_angle_integrated()) - - def get_speed(self) -> float: - # velocity is in rot/s, return in m/s - return self.drive.get_velocity().value - - def get_distance_traveled(self) -> float: - return self.drive.get_position().value - - def set(self, desired_state: SwerveModuleState): - if self.module_locked: - desired_state = SwerveModuleState(0, self.central_angle) - - # smooth wheel velocity vector - if self.do_smooth: - self.state = rate_limit_module(self.state, desired_state, self.accel_limit) - else: - self.state = desired_state - current_angle = self.get_rotation() - self.state = SwerveModuleState.optimize(self.state, current_angle) - - if abs(self.state.speed) < 0.01 and not self.module_locked: - self.drive.set_control( - self.drive_request.with_velocity(0).with_feed_forward(0) - ) - self.steer.set_control(self.stop_request) - return - - target_displacement = self.state.angle - current_angle - target_angle = self.state.angle.radians() - self.steer_request = PositionDutyCycle(target_angle / math.tau) - self.steer.set_control(self.steer_request) - - # rescale the speed target based on how close we are to being correctly aligned - target_speed = self.state.speed * target_displacement.cos() ** 2 - speed_volt = self.drive_ff.calculate(target_speed) - - # original position change/100ms, new m/s -> rot/s - self.drive.set_control( - self.drive_request.with_velocity(target_speed).with_feed_forward(speed_volt) - ) - - def sync_steer_encoder(self) -> None: - self.steer.set_position(self.get_angle_absolute()) - - def get_position(self) -> SwerveModulePosition: - return SwerveModulePosition(self.get_distance_traveled(), self.get_rotation()) - - def get(self) -> SwerveModuleState: - return SwerveModuleState(self.get_speed(), self.get_rotation()) - - -class ChassisComponent: - # metres between centre of left and right wheels - TRACK_WIDTH = 0.467 - # metres between centre of front and back wheels - WHEEL_BASE = 0.467 - - # size including bumpers - LENGTH = 0.600 + 2 * 0.09 - WIDTH = LENGTH - - DRIVE_CURRENT_THRESHOLD = 35 - - HEADING_TOLERANCE = math.radians(1) - - # maxiumum speed for any wheel - max_wheel_speed = FALCON_FREE_RPS * SwerveModule.DRIVE_MOTOR_REV_TO_METRES - - control_loop_wait_time: float - - chassis_speeds = magicbot.will_reset_to(ChassisSpeeds(0, 0, 0)) - field: wpilib.Field2d - logger: Logger - - send_modules = magicbot.tunable(False) - do_fudge = magicbot.tunable(True) - do_smooth = magicbot.tunable(True) - swerve_lock = magicbot.tunable(False) - - # TODO: Read from positions.py once autonomous is finished - - def __init__(self) -> None: - self.imu = navx.AHRS.create_spi() - self.heading_controller = ProfiledPIDControllerRadians( - 3, 0, 0, TrapezoidProfileRadians.Constraints(100, 100) - ) - self.heading_controller.enableContinuousInput(-math.pi, math.pi) - self.snapping_to_heading = False - self.heading_controller.setTolerance(self.HEADING_TOLERANCE) - - self.on_red_alliance = False - - self.modules = ( - # Front Left - SwerveModule( - self.WHEEL_BASE / 2, - self.TRACK_WIDTH / 2, - TalonIds.drive_1, - TalonIds.steer_1, - CancoderIds.swerve_1, - ), - # Back Left - SwerveModule( - -self.WHEEL_BASE / 2, - self.TRACK_WIDTH / 2, - TalonIds.drive_2, - TalonIds.steer_2, - CancoderIds.swerve_2, - ), - # Back Right - SwerveModule( - -self.WHEEL_BASE / 2, - -self.TRACK_WIDTH / 2, - TalonIds.drive_3, - TalonIds.steer_3, - CancoderIds.swerve_3, - ), - # Front Right - SwerveModule( - self.WHEEL_BASE / 2, - -self.TRACK_WIDTH / 2, - TalonIds.drive_4, - TalonIds.steer_4, - CancoderIds.swerve_4, - ), - ) - - self.kinematics = SwerveDrive4Kinematics( - self.modules[0].translation, - self.modules[1].translation, - self.modules[2].translation, - self.modules[3].translation, - ) - self.sync_all() - self.imu.zeroYaw() - self.imu.resetDisplacement() - - nt = ntcore.NetworkTableInstance.getDefault().getTable("/components/chassis") - module_states_table = nt.getSubTable("module_states") - self.setpoints_publisher = module_states_table.getStructArrayTopic( - "setpoints", SwerveModuleState - ).publish() - self.measurements_publisher = module_states_table.getStructArrayTopic( - "measured", SwerveModuleState - ).publish() - - wpilib.SmartDashboard.putData("Heading PID", self.heading_controller) - - def get_velocity(self) -> ChassisSpeeds: - return self.kinematics.toChassisSpeeds(self.get_module_states()) - - @feedback - def imu_rotation(self) -> float: - return self.imu.getAngle() - - def get_module_states( - self, - ) -> tuple[ - SwerveModuleState, SwerveModuleState, SwerveModuleState, SwerveModuleState - ]: - return ( - self.modules[0].get(), - self.modules[1].get(), - self.modules[2].get(), - self.modules[3].get(), - ) - - def setup(self) -> None: - initial_pose = TeamPoses.RED_TEST_POSE if is_red() else TeamPoses.BLUE_TEST_POSE - - self.estimator = SwerveDrive4PoseEstimator( - self.kinematics, - self.imu.getRotation2d(), - self.get_module_positions(), - initial_pose, - stateStdDevs=(0.05, 0.05, 0.01), - visionMeasurementStdDevs=(0.4, 0.4, 0.03), - ) - self.field_obj = self.field.getObject("fused_pose") - self.set_pose(initial_pose) - - def drive_field(self, vx: float, vy: float, omega: float) -> None: - """Field oriented drive commands""" - current_heading = self.get_rotation() - self.chassis_speeds = ChassisSpeeds.fromFieldRelativeSpeeds( - vx, vy, omega, current_heading - ) - - def to_field_oriented(self, chassis_speed: ChassisSpeeds) -> ChassisSpeeds: - current_heading = self.get_rotation() - return ChassisSpeeds.fromRobotRelativeSpeeds(chassis_speed, current_heading) - - def drive_local(self, vx: float, vy: float, omega: float) -> None: - """Robot oriented drive commands""" - self.chassis_speeds = ChassisSpeeds(vx, vy, omega) - - def snap_to_heading(self, heading: float) -> None: - """set a heading target for the heading controller""" - self.snapping_to_heading = True - self.heading_controller.setGoal(heading) - - def stop_snapping(self) -> None: - """stops the heading_controller""" - self.snapping_to_heading = False - - def execute(self) -> None: - # rotate desired velocity to compensate for skew caused by discretization - # see https://www.chiefdelphi.com/t/field-relative-swervedrive-drift-even-with-simulated-perfect-modules/413892/ - - if self.snapping_to_heading: - self.chassis_speeds.omega = self.heading_controller.calculate( - self.get_rotation().radians() - ) - else: - self.heading_controller.reset( - self.get_rotation().radians(), self.get_rotational_velocity() - ) - - if self.do_fudge: - # in the sim i found using 5 instead of 0.5 did a lot better - desired_speed_translation = Translation2d( - self.chassis_speeds.vx, self.chassis_speeds.vy - ).rotateBy( - Rotation2d(-self.chassis_speeds.omega * 5 * self.control_loop_wait_time) - ) - desired_speeds = ChassisSpeeds( - desired_speed_translation.x, - desired_speed_translation.y, - self.chassis_speeds.omega, - ) - else: - desired_speeds = self.chassis_speeds - - if self.swerve_lock: - self.do_smooth = False - - desired_states = self.kinematics.toSwerveModuleStates(desired_speeds) - desired_states = self.kinematics.desaturateWheelSpeeds( - desired_states, attainableMaxSpeed=self.max_wheel_speed - ) - - for state, module in zip(desired_states, self.modules): - module.module_locked = self.swerve_lock - module.do_smooth = self.do_smooth - module.set(state) - - self.update_odometry() - - def on_enable(self) -> None: - """update the odometry so the pose estimator doesn't have an empty buffer - - While we should be building the pose buffer while disabled, - this accounts for the edge case of crashing mid match and immediately enabling with an empty buffer - """ - self.update_alliance() - self.update_odometry() - - @magicbot.feedback - def get_imu_speed(self) -> float: - return math.hypot(self.imu.getVelocityX(), self.imu.getVelocityY()) - - def get_rotational_velocity(self) -> float: - return math.radians(-self.imu.getRate()) - - def lock_swerve(self) -> None: - self.swerve_lock = True - - def unlock_swerve(self) -> None: - self.swerve_lock = False - - def update_alliance(self) -> None: - # Check whether our alliance has "changed" - # If so, it means we have an update from the FMS and need to re-init the odom - if is_red() != self.on_red_alliance: - self.on_red_alliance = is_red() - if self.on_red_alliance: - self.set_pose(TeamPoses.RED_TEST_POSE) - else: - self.set_pose(TeamPoses.BLUE_TEST_POSE) - - def update_odometry(self) -> None: - self.estimator.update(self.imu.getRotation2d(), self.get_module_positions()) - self.field_obj.setPose(self.get_pose()) - if self.send_modules: - self.setpoints_publisher.set([module.state for module in self.modules]) - self.measurements_publisher.set([module.get() for module in self.modules]) - - def sync_all(self) -> None: - for m in self.modules: - m.sync_steer_encoder() - - def set_pose(self, pose: Pose2d) -> None: - self.estimator.resetPosition( - self.imu.getRotation2d(), self.get_module_positions(), pose - ) - self.field.setRobotPose(pose) - self.field_obj.setPose(pose) - - def reset_yaw(self) -> None: - """Sets pose to current pose but with a heading of forwards""" - cur_pose = self.estimator.getEstimatedPosition() - self.set_pose( - Pose2d(cur_pose.translation(), Rotation2d(math.pi if is_red() else 0)) - ) - - def reset_odometry(self) -> None: - """Reset odometry to current team's podium""" - if is_red(): - self.set_pose(TeamPoses.RED_PODIUM) - else: - self.set_pose(TeamPoses.BLUE_PODIUM) - - def get_module_positions( - self, - ) -> tuple[ - SwerveModulePosition, - SwerveModulePosition, - SwerveModulePosition, - SwerveModulePosition, - ]: - return ( - self.modules[0].get_position(), - self.modules[1].get_position(), - self.modules[2].get_position(), - self.modules[3].get_position(), - ) - - def get_pose(self) -> Pose2d: - """Get the current location of the robot relative to ???""" - return self.estimator.getEstimatedPosition() - - def get_rotation(self) -> Rotation2d: - """Get the current heading of the robot.""" - return self.get_pose().rotation() - - @feedback - def at_desired_heading(self) -> bool: - return self.heading_controller.atGoal() +from logging import Logger +import math + +from phoenix6.hardware import TalonFX, CANcoder +from phoenix6.controls import VoltageOut, VelocityVoltage, PositionDutyCycle +from phoenix6.signals import InvertedValue, NeutralModeValue +from phoenix6.configs import ( + ClosedLoopGeneralConfigs, + MotorOutputConfigs, + FeedbackConfigs, + Slot0Configs, +) +import magicbot +import navx +import ntcore +import wpilib +from wpimath.kinematics import ( + SwerveDrive4Kinematics, + ChassisSpeeds, + SwerveModuleState, + SwerveModulePosition, +) +from wpimath.geometry import Translation2d, Rotation2d, Pose2d +from wpimath.estimator import SwerveDrive4PoseEstimator +from wpimath.controller import SimpleMotorFeedforwardMeters +from wpimath.trajectory import TrapezoidProfileRadians +from wpimath.controller import ProfiledPIDControllerRadians + +from magicbot import feedback + +from utilities.functions import rate_limit_module +from utilities.game import is_red +from utilities.ctre import FALCON_FREE_RPS +from utilities.position import TeamPoses +from ids import CancoderIds, TalonIds + + +class SwerveModule: + DRIVE_GEAR_RATIO = (14.0 / 50.0) * (25.0 / 19.0) * (15.0 / 45.0) + STEER_GEAR_RATIO = (14 / 50) * (10 / 60) + WHEEL_CIRCUMFERENCE = 4 * 2.54 / 100 * math.pi + + DRIVE_MOTOR_REV_TO_METRES = WHEEL_CIRCUMFERENCE * DRIVE_GEAR_RATIO + STEER_MOTOR_REV_TO_RAD = math.tau * STEER_GEAR_RATIO + + # limit the acceleration of the commanded speeds of the robot to what is actually + # achiveable without the wheels slipping. This is done to improve odometry + accel_limit = 15 # m/s^2 + + def __init__( + self, + x: float, + y: float, + drive_id: int, + steer_id: int, + encoder_id: int, + *, + drive_reversed: bool = False, + ): + """ + x, y: where the module is relative to the center of the robot + *_id: can ids of steer and drive motors and absolute encoder + """ + self.translation = Translation2d(x, y) + self.state = SwerveModuleState(0, Rotation2d(0)) + self.do_smooth = True + + # Create Motor and encoder objects + self.steer = TalonFX(steer_id) + self.drive = TalonFX(drive_id) + self.drive_id = drive_id + self.encoder = CANcoder(encoder_id) + + # Reduce CAN status frame rates before configuring + self.steer.get_fault_field().set_update_frequency( + frequency_hz=4, timeout_seconds=0.01 + ) + self.drive.get_fault_field().set_update_frequency( + frequency_hz=4, timeout_seconds=0.01 + ) + + # Configure steer motor + steer_config = self.steer.configurator + + steer_motor_config = MotorOutputConfigs() + steer_motor_config.neutral_mode = NeutralModeValue.BRAKE + # The SDS Mk4i rotation has one pair of gears. + steer_motor_config.inverted = InvertedValue.CLOCKWISE_POSITIVE + + steer_gear_ratio_config = FeedbackConfigs().with_sensor_to_mechanism_ratio( + 1 / self.STEER_GEAR_RATIO + ) + + # configuration for motor pid + steer_pid = Slot0Configs().with_k_p(2.4206).with_k_i(0).with_k_d(0.060654) + steer_closed_loop_config = ClosedLoopGeneralConfigs() + steer_closed_loop_config.continuous_wrap = True + + steer_config.apply(steer_motor_config) + steer_config.apply(steer_pid, 0.01) + steer_config.apply(steer_gear_ratio_config) + steer_config.apply(steer_closed_loop_config) + + # Configure drive motor + drive_config = self.drive.configurator + + drive_motor_config = MotorOutputConfigs() + drive_motor_config.neutral_mode = NeutralModeValue.BRAKE + drive_motor_config.inverted = ( + InvertedValue.CLOCKWISE_POSITIVE + if drive_reversed + else InvertedValue.COUNTER_CLOCKWISE_POSITIVE + ) + + drive_gear_ratio_config = FeedbackConfigs().with_sensor_to_mechanism_ratio( + 1 / self.DRIVE_MOTOR_REV_TO_METRES + ) + + # configuration for motor pid and feedforward + self.drive_pid = Slot0Configs().with_k_p(1.0868).with_k_i(0).with_k_d(0) + self.drive_ff = SimpleMotorFeedforwardMeters(kS=0.15172, kV=2.8305, kA=0.082659) + + drive_config.apply(drive_motor_config) + drive_config.apply(self.drive_pid, 0.01) + drive_config.apply(drive_gear_ratio_config) + + self.central_angle = Rotation2d(x, y) + self.module_locked = False + + self.sync_steer_encoder() + + self.drive_request = VelocityVoltage(0) + self.stop_request = VoltageOut(0) + + def get_angle_absolute(self) -> float: + """Gets steer angle (rot) from absolute encoder""" + return self.encoder.get_absolute_position().value + + def get_angle_integrated(self) -> float: + """Gets steer angle from motor's integrated relative encoder""" + return self.steer.get_position().value * math.tau + + def get_rotation(self) -> Rotation2d: + """Get the steer angle as a Rotation2d""" + return Rotation2d(self.get_angle_integrated()) + + def get_speed(self) -> float: + # velocity is in rot/s, return in m/s + return self.drive.get_velocity().value + + def get_distance_traveled(self) -> float: + return self.drive.get_position().value + + def set(self, desired_state: SwerveModuleState): + if self.module_locked: + desired_state = SwerveModuleState(0, self.central_angle) + + # smooth wheel velocity vector + if self.do_smooth: + self.state = rate_limit_module(self.state, desired_state, self.accel_limit) + else: + self.state = desired_state + current_angle = self.get_rotation() + self.state = SwerveModuleState.optimize(self.state, current_angle) + + if abs(self.state.speed) < 0.01 and not self.module_locked: + self.drive.set_control( + self.drive_request.with_velocity(0).with_feed_forward(0) + ) + self.steer.set_control(self.stop_request) + return + + target_displacement = self.state.angle - current_angle + target_angle = self.state.angle.radians() + self.steer_request = PositionDutyCycle(target_angle / math.tau) + self.steer.set_control(self.steer_request) + + # rescale the speed target based on how close we are to being correctly aligned + target_speed = self.state.speed * target_displacement.cos() ** 2 + speed_volt = self.drive_ff.calculate(target_speed) + + # original position change/100ms, new m/s -> rot/s + self.drive.set_control( + self.drive_request.with_velocity(target_speed).with_feed_forward(speed_volt) + ) + + def sync_steer_encoder(self) -> None: + self.steer.set_position(self.get_angle_absolute()) + + def get_position(self) -> SwerveModulePosition: + return SwerveModulePosition(self.get_distance_traveled(), self.get_rotation()) + + def get(self) -> SwerveModuleState: + return SwerveModuleState(self.get_speed(), self.get_rotation()) + + +class ChassisComponent: + # metres between centre of left and right wheels + TRACK_WIDTH = 0.467 + # metres between centre of front and back wheels + WHEEL_BASE = 0.467 + + # size including bumpers + LENGTH = 0.600 + 2 * 0.09 + WIDTH = LENGTH + + DRIVE_CURRENT_THRESHOLD = 35 + + HEADING_TOLERANCE = math.radians(1) + + # maxiumum speed for any wheel + max_wheel_speed = FALCON_FREE_RPS * SwerveModule.DRIVE_MOTOR_REV_TO_METRES + + control_loop_wait_time: float + + chassis_speeds = magicbot.will_reset_to(ChassisSpeeds(0, 0, 0)) + field: wpilib.Field2d + logger: Logger + + send_modules = magicbot.tunable(False) + do_fudge = magicbot.tunable(True) + do_smooth = magicbot.tunable(True) + swerve_lock = magicbot.tunable(False) + + # TODO: Read from positions.py once autonomous is finished + + def __init__(self) -> None: + self.imu = navx.AHRS.create_spi() + self.heading_controller = ProfiledPIDControllerRadians( + 3, 0, 0, TrapezoidProfileRadians.Constraints(100, 100) + ) + self.heading_controller.enableContinuousInput(-math.pi, math.pi) + self.snapping_to_heading = False + self.heading_controller.setTolerance(self.HEADING_TOLERANCE) + + self.on_red_alliance = False + + self.modules = ( + # Front Left + SwerveModule( + self.WHEEL_BASE / 2, + self.TRACK_WIDTH / 2, + TalonIds.drive_1, + TalonIds.steer_1, + CancoderIds.swerve_1, + ), + # Back Left + SwerveModule( + -self.WHEEL_BASE / 2, + self.TRACK_WIDTH / 2, + TalonIds.drive_2, + TalonIds.steer_2, + CancoderIds.swerve_2, + ), + # Back Right + SwerveModule( + -self.WHEEL_BASE / 2, + -self.TRACK_WIDTH / 2, + TalonIds.drive_3, + TalonIds.steer_3, + CancoderIds.swerve_3, + ), + # Front Right + SwerveModule( + self.WHEEL_BASE / 2, + -self.TRACK_WIDTH / 2, + TalonIds.drive_4, + TalonIds.steer_4, + CancoderIds.swerve_4, + ), + ) + + self.kinematics = SwerveDrive4Kinematics( + self.modules[0].translation, + self.modules[1].translation, + self.modules[2].translation, + self.modules[3].translation, + ) + self.sync_all() + self.imu.zeroYaw() + self.imu.resetDisplacement() + + nt = ntcore.NetworkTableInstance.getDefault().getTable("/components/chassis") + module_states_table = nt.getSubTable("module_states") + self.setpoints_publisher = module_states_table.getStructArrayTopic( + "setpoints", SwerveModuleState + ).publish() + self.measurements_publisher = module_states_table.getStructArrayTopic( + "measured", SwerveModuleState + ).publish() + + wpilib.SmartDashboard.putData("Heading PID", self.heading_controller) + + def get_velocity(self) -> ChassisSpeeds: + return self.kinematics.toChassisSpeeds(self.get_module_states()) + + @feedback + def imu_rotation(self) -> float: + return self.imu.getAngle() + + def get_module_states( + self, + ) -> tuple[ + SwerveModuleState, SwerveModuleState, SwerveModuleState, SwerveModuleState + ]: + return ( + self.modules[0].get(), + self.modules[1].get(), + self.modules[2].get(), + self.modules[3].get(), + ) + + def setup(self) -> None: + initial_pose = TeamPoses.RED_TEST_POSE if is_red() else TeamPoses.BLUE_TEST_POSE + + self.estimator = SwerveDrive4PoseEstimator( + self.kinematics, + self.imu.getRotation2d(), + self.get_module_positions(), + initial_pose, + stateStdDevs=(0.05, 0.05, 0.01), + visionMeasurementStdDevs=(0.4, 0.4, 0.03), + ) + self.field_obj = self.field.getObject("fused_pose") + self.set_pose(initial_pose) + + def drive_field(self, vx: float, vy: float, omega: float) -> None: + """Field oriented drive commands""" + current_heading = self.get_rotation() + self.chassis_speeds = ChassisSpeeds.fromFieldRelativeSpeeds( + vx, vy, omega, current_heading + ) + + def to_field_oriented(self, chassis_speed: ChassisSpeeds) -> ChassisSpeeds: + current_heading = self.get_rotation() + return ChassisSpeeds.fromRobotRelativeSpeeds(chassis_speed, current_heading) + + def drive_local(self, vx: float, vy: float, omega: float) -> None: + """Robot oriented drive commands""" + self.chassis_speeds = ChassisSpeeds(vx, vy, omega) + + def snap_to_heading(self, heading: float) -> None: + """set a heading target for the heading controller""" + self.snapping_to_heading = True + self.heading_controller.setGoal(heading) + + def stop_snapping(self) -> None: + """stops the heading_controller""" + self.snapping_to_heading = False + + def execute(self) -> None: + # rotate desired velocity to compensate for skew caused by discretization + # see https://www.chiefdelphi.com/t/field-relative-swervedrive-drift-even-with-simulated-perfect-modules/413892/ + + if self.snapping_to_heading: + self.chassis_speeds.omega = self.heading_controller.calculate( + self.get_rotation().radians() + ) + else: + self.heading_controller.reset( + self.get_rotation().radians(), self.get_rotational_velocity() + ) + + if self.do_fudge: + # in the sim i found using 5 instead of 0.5 did a lot better + desired_speed_translation = Translation2d( + self.chassis_speeds.vx, self.chassis_speeds.vy + ).rotateBy( + Rotation2d(-self.chassis_speeds.omega * 5 * self.control_loop_wait_time) + ) + desired_speeds = ChassisSpeeds( + desired_speed_translation.x, + desired_speed_translation.y, + self.chassis_speeds.omega, + ) + else: + desired_speeds = self.chassis_speeds + + if self.swerve_lock: + self.do_smooth = False + + desired_states = self.kinematics.toSwerveModuleStates(desired_speeds) + desired_states = self.kinematics.desaturateWheelSpeeds( + desired_states, attainableMaxSpeed=self.max_wheel_speed + ) + + for state, module in zip(desired_states, self.modules): + module.module_locked = self.swerve_lock + module.do_smooth = self.do_smooth + module.set(state) + + self.update_odometry() + + def on_enable(self) -> None: + """update the odometry so the pose estimator doesn't have an empty buffer + + While we should be building the pose buffer while disabled, + this accounts for the edge case of crashing mid match and immediately enabling with an empty buffer + """ + self.update_alliance() + self.update_odometry() + + @magicbot.feedback + def get_imu_speed(self) -> float: + return math.hypot(self.imu.getVelocityX(), self.imu.getVelocityY()) + + def get_rotational_velocity(self) -> float: + return math.radians(-self.imu.getRate()) + + def lock_swerve(self) -> None: + self.swerve_lock = True + + def unlock_swerve(self) -> None: + self.swerve_lock = False + + def update_alliance(self) -> None: + # Check whether our alliance has "changed" + # If so, it means we have an update from the FMS and need to re-init the odom + if is_red() != self.on_red_alliance: + self.on_red_alliance = is_red() + if self.on_red_alliance: + self.set_pose(TeamPoses.RED_TEST_POSE) + else: + self.set_pose(TeamPoses.BLUE_TEST_POSE) + + def update_odometry(self) -> None: + self.estimator.update(self.imu.getRotation2d(), self.get_module_positions()) + self.field_obj.setPose(self.get_pose()) + if self.send_modules: + self.setpoints_publisher.set([module.state for module in self.modules]) + self.measurements_publisher.set([module.get() for module in self.modules]) + + def sync_all(self) -> None: + for m in self.modules: + m.sync_steer_encoder() + + def set_pose(self, pose: Pose2d) -> None: + self.estimator.resetPosition( + self.imu.getRotation2d(), self.get_module_positions(), pose + ) + self.field.setRobotPose(pose) + self.field_obj.setPose(pose) + + def reset_yaw(self) -> None: + """Sets pose to current pose but with a heading of forwards""" + cur_pose = self.estimator.getEstimatedPosition() + self.set_pose( + Pose2d(cur_pose.translation(), Rotation2d(math.pi if is_red() else 0)) + ) + + def reset_odometry(self) -> None: + """Reset odometry to current team's podium""" + if is_red(): + self.set_pose(TeamPoses.RED_PODIUM) + else: + self.set_pose(TeamPoses.BLUE_PODIUM) + + def get_module_positions( + self, + ) -> tuple[ + SwerveModulePosition, + SwerveModulePosition, + SwerveModulePosition, + SwerveModulePosition, + ]: + return ( + self.modules[0].get_position(), + self.modules[1].get_position(), + self.modules[2].get_position(), + self.modules[3].get_position(), + ) + + def get_pose(self) -> Pose2d: + """Get the current location of the robot relative to ???""" + return self.estimator.getEstimatedPosition() + + def get_rotation(self) -> Rotation2d: + """Get the current heading of the robot.""" + return self.get_pose().rotation() + + @feedback + def at_desired_heading(self) -> bool: + return self.heading_controller.atGoal() diff --git a/vision.py b/components/vision.py similarity index 97% rename from vision.py rename to components/vision.py index f5b4f627..d0b710bd 100644 --- a/vision.py +++ b/components/vision.py @@ -1,192 +1,192 @@ -import math -import time -from typing import Optional - -import wpilib -import wpiutil.log -from magicbot import tunable, feedback -from photonlibpy.photonCamera import PhotonCamera -from photonlibpy.photonTrackedTarget import PhotonTrackedTarget -from wpimath import objectToRobotPose -from wpimath.geometry import Pose2d, Rotation3d, Transform3d, Translation3d, Pose3d - -from components.chassis import ChassisComponent -from utilities.game import apriltag_layout - - -class VisualLocalizer: - """ - This localizes the robot from AprilTags on the field, - using information from a single PhotonVision camera. - """ - - # Give bias to the best pose by multiplying this const to the alt dist - BEST_POSE_BIAS = 1.2 - - # Time since the last target sighting we allow before informing drivers - TIMEOUT = 1.0 # s - - add_to_estimator = tunable(True) - should_log = tunable(True) - - last_pose_z = tunable(0.0, writeDefault=False) - linear_vision_uncertainty = tunable(0.3) - rotation_vision_uncertainty = tunable(0.08) - reproj_error_threshold = 1 - - def __init__( - self, - # The name of the camera in PhotonVision. - name: str, - # Position of the camera relative to the center of the robot - pos: Translation3d, - # The camera rotation. - rot: Rotation3d, - field: wpilib.Field2d, - data_log: wpiutil.log.DataLog, - chassis: ChassisComponent, - ) -> None: - self.camera = PhotonCamera(name) - self.robot_to_camera = Transform3d(pos, rot) - self.camera_to_robot = self.robot_to_camera.inverse() - self.last_timestamp = -1 - self.last_recieved_timestep = -1.0 - - self.single_best_log = field.getObject(name + "single_best_log") - self.single_alt_log = field.getObject(name + "single_alt_log") - self.multi_best_log = field.getObject(name + "multi_best_log") - self.multi_alt_log = field.getObject(name + "multi_alt_log") - self.field_pos_obj = field.getObject(name + "vision_pose") - self.pose_log_entry = wpiutil.log.FloatArrayLogEntry( - data_log, name + "vision_pose" - ) - - self.chassis = chassis - self.current_reproj = 0.0 - - @feedback - def reproj(self) -> float: - return self.current_reproj - - def execute(self) -> None: - # stop warnings in simulation - if wpilib.RobotBase.isSimulation(): - return - - results = self.camera.getLatestResult() - # if results didn't see any targets - if not results.getTargets(): - return - - # if we have already processed these results - timestamp = results.getTimestamp() - - if timestamp == self.last_timestamp: - return - self.last_recieved_timestep = time.monotonic() - self.last_timestamp = timestamp - - if results.multiTagResult.estimatedPose.isPresent: - p = results.multiTagResult.estimatedPose - pose = (Pose3d() + p.best + self.camera_to_robot).toPose2d() - reprojectionErr = p.bestReprojError - self.current_reproj = reprojectionErr - - self.field_pos_obj.setPose(pose) - - if ( - self.add_to_estimator - and self.current_reproj < self.reproj_error_threshold - ): - self.chassis.estimator.addVisionMeasurement( - pose, - timestamp, - ( - self.linear_vision_uncertainty, - self.linear_vision_uncertainty, - self.rotation_vision_uncertainty, - ), - ) - - if self.should_log: - self.multi_best_log.setPose( - Pose2d(p.best.x, p.best.y, p.best.rotation().toRotation2d()) - ) - self.multi_alt_log.setPose( - Pose2d(p.alt.x, p.alt.y, p.alt.rotation().toRotation2d()) - ) - else: - for target in results.getTargets(): - # filter out likely bad targets - if target.getPoseAmbiguity() > 0.25: - continue - - poses = estimate_poses_from_apriltag(self.robot_to_camera, target) - if poses is None: - # tag doesn't exist - continue - - best, alt, self.last_pose_z = poses - pose = choose_pose( - best, - alt, - self.chassis.get_pose(), - ) - - self.field_pos_obj.setPose(pose) - self.chassis.estimator.addVisionMeasurement(pose, timestamp) - - if self.should_log: - self.single_best_log.setPose( - Pose2d( - target.bestCameraToTarget.x, - target.bestCameraToTarget.y, - target.bestCameraToTarget.rotation().toRotation2d(), - ) - ) - self.single_alt_log.setPose( - Pose2d( - target.altCameraToTarget.x, - target.altCameraToTarget.y, - target.altCameraToTarget.rotation().toRotation2d(), - ) - ) - - def sees_target(self): - return time.monotonic() - self.last_recieved_timestep < self.TIMEOUT - - -def estimate_poses_from_apriltag( - robot_to_camera: Transform3d, target: PhotonTrackedTarget -) -> Optional[tuple[Pose2d, Pose2d, float]]: - tag_id = target.getFiducialId() - tag_pose = apriltag_layout.getTagPose(tag_id) - if tag_pose is None: - return None - - best_pose = objectToRobotPose( - tag_pose, target.getBestCameraToTarget(), robot_to_camera - ) - alternate_pose = objectToRobotPose( - tag_pose, target.getAlternateCameraToTarget(), robot_to_camera - ) - return best_pose.toPose2d(), alternate_pose.toPose2d(), best_pose.z - - -def get_target_skew(target: PhotonTrackedTarget) -> float: - tag_to_cam = target.getBestCameraToTarget().inverse() - return math.atan2(tag_to_cam.y, tag_to_cam.x) - - -def choose_pose(best_pose: Pose2d, alternate_pose: Pose2d, cur_robot: Pose2d) -> Pose2d: - """Picks either the best or alternate pose estimate""" - best_dist = best_pose.translation().distance(cur_robot.translation()) - alternate_dist = ( - alternate_pose.translation().distance(cur_robot.translation()) - * VisualLocalizer.BEST_POSE_BIAS - ) - - if best_dist < alternate_dist: - return best_pose - else: - return alternate_pose +import math +import time +from typing import Optional + +import wpilib +import wpiutil.log +from magicbot import tunable, feedback +from photonlibpy.photonCamera import PhotonCamera +from photonlibpy.photonTrackedTarget import PhotonTrackedTarget +from wpimath import objectToRobotPose +from wpimath.geometry import Pose2d, Rotation3d, Transform3d, Translation3d, Pose3d + +from components.chassis import ChassisComponent +from utilities.game import apriltag_layout + + +class VisualLocalizer: + """ + This localizes the robot from AprilTags on the field, + using information from a single PhotonVision camera. + """ + + # Give bias to the best pose by multiplying this const to the alt dist + BEST_POSE_BIAS = 1.2 + + # Time since the last target sighting we allow before informing drivers + TIMEOUT = 1.0 # s + + add_to_estimator = tunable(True) + should_log = tunable(True) + + last_pose_z = tunable(0.0, writeDefault=False) + linear_vision_uncertainty = tunable(0.3) + rotation_vision_uncertainty = tunable(0.08) + reproj_error_threshold = 1 + + def __init__( + self, + # The name of the camera in PhotonVision. + name: str, + # Position of the camera relative to the center of the robot + pos: Translation3d, + # The camera rotation. + rot: Rotation3d, + field: wpilib.Field2d, + data_log: wpiutil.log.DataLog, + chassis: ChassisComponent, + ) -> None: + self.camera = PhotonCamera(name) + self.robot_to_camera = Transform3d(pos, rot) + self.camera_to_robot = self.robot_to_camera.inverse() + self.last_timestamp = -1 + self.last_recieved_timestep = -1.0 + + self.single_best_log = field.getObject(name + "single_best_log") + self.single_alt_log = field.getObject(name + "single_alt_log") + self.multi_best_log = field.getObject(name + "multi_best_log") + self.multi_alt_log = field.getObject(name + "multi_alt_log") + self.field_pos_obj = field.getObject(name + "vision_pose") + self.pose_log_entry = wpiutil.log.FloatArrayLogEntry( + data_log, name + "vision_pose" + ) + + self.chassis = chassis + self.current_reproj = 0.0 + + @feedback + def reproj(self) -> float: + return self.current_reproj + + def execute(self) -> None: + # stop warnings in simulation + if wpilib.RobotBase.isSimulation(): + return + + results = self.camera.getLatestResult() + # if results didn't see any targets + if not results.getTargets(): + return + + # if we have already processed these results + timestamp = results.getTimestamp() + + if timestamp == self.last_timestamp: + return + self.last_recieved_timestep = time.monotonic() + self.last_timestamp = timestamp + + if results.multiTagResult.estimatedPose.isPresent: + p = results.multiTagResult.estimatedPose + pose = (Pose3d() + p.best + self.camera_to_robot).toPose2d() + reprojectionErr = p.bestReprojError + self.current_reproj = reprojectionErr + + self.field_pos_obj.setPose(pose) + + if ( + self.add_to_estimator + and self.current_reproj < self.reproj_error_threshold + ): + self.chassis.estimator.addVisionMeasurement( + pose, + timestamp, + ( + self.linear_vision_uncertainty, + self.linear_vision_uncertainty, + self.rotation_vision_uncertainty, + ), + ) + + if self.should_log: + self.multi_best_log.setPose( + Pose2d(p.best.x, p.best.y, p.best.rotation().toRotation2d()) + ) + self.multi_alt_log.setPose( + Pose2d(p.alt.x, p.alt.y, p.alt.rotation().toRotation2d()) + ) + else: + for target in results.getTargets(): + # filter out likely bad targets + if target.getPoseAmbiguity() > 0.25: + continue + + poses = estimate_poses_from_apriltag(self.robot_to_camera, target) + if poses is None: + # tag doesn't exist + continue + + best, alt, self.last_pose_z = poses + pose = choose_pose( + best, + alt, + self.chassis.get_pose(), + ) + + self.field_pos_obj.setPose(pose) + self.chassis.estimator.addVisionMeasurement(pose, timestamp) + + if self.should_log: + self.single_best_log.setPose( + Pose2d( + target.bestCameraToTarget.x, + target.bestCameraToTarget.y, + target.bestCameraToTarget.rotation().toRotation2d(), + ) + ) + self.single_alt_log.setPose( + Pose2d( + target.altCameraToTarget.x, + target.altCameraToTarget.y, + target.altCameraToTarget.rotation().toRotation2d(), + ) + ) + + def sees_target(self): + return time.monotonic() - self.last_recieved_timestep < self.TIMEOUT + + +def estimate_poses_from_apriltag( + robot_to_camera: Transform3d, target: PhotonTrackedTarget +) -> Optional[tuple[Pose2d, Pose2d, float]]: + tag_id = target.getFiducialId() + tag_pose = apriltag_layout.getTagPose(tag_id) + if tag_pose is None: + return None + + best_pose = objectToRobotPose( + tag_pose, target.getBestCameraToTarget(), robot_to_camera + ) + alternate_pose = objectToRobotPose( + tag_pose, target.getAlternateCameraToTarget(), robot_to_camera + ) + return best_pose.toPose2d(), alternate_pose.toPose2d(), best_pose.z + + +def get_target_skew(target: PhotonTrackedTarget) -> float: + tag_to_cam = target.getBestCameraToTarget().inverse() + return math.atan2(tag_to_cam.y, tag_to_cam.x) + + +def choose_pose(best_pose: Pose2d, alternate_pose: Pose2d, cur_robot: Pose2d) -> Pose2d: + """Picks either the best or alternate pose estimate""" + best_dist = best_pose.translation().distance(cur_robot.translation()) + alternate_dist = ( + alternate_pose.translation().distance(cur_robot.translation()) + * VisualLocalizer.BEST_POSE_BIAS + ) + + if best_dist < alternate_dist: + return best_pose + else: + return alternate_pose From 2f773aec1e3f2337ccf4ccb69336a6e387bad871 Mon Sep 17 00:00:00 2001 From: Beana1234 Date: Tue, 22 Oct 2024 19:35:01 +1100 Subject: [PATCH 08/20] add ids file --- ids.py | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 ids.py diff --git a/ids.py b/ids.py new file mode 100644 index 00000000..0b7f6df2 --- /dev/null +++ b/ids.py @@ -0,0 +1,39 @@ +import enum + + +@enum.unique +class TalonIds(enum.IntEnum): + drive_1 = 1 + steer_1 = 5 + + drive_2 = 2 + steer_2 = 6 + + drive_3 = 3 + steer_3 = 7 + + drive_4 = 4 + steer_4 = 8 + + +@enum.unique +class CancoderIds(enum.IntEnum): + swerve_1 = 1 + swerve_2 = 2 + swerve_3 = 3 + swerve_4 = 4 + + +@enum.unique +class SparkMaxIds(enum.IntEnum): + pass + + +@enum.unique +class DioChannels(enum.IntEnum): + pass + + +@enum.unique +class PwmChannels(enum.IntEnum): + pass From b4fdbdf7d0cdec8bf15c4b2273331890f424adb3 Mon Sep 17 00:00:00 2001 From: Beana1234 Date: Tue, 22 Oct 2024 19:45:16 +1100 Subject: [PATCH 09/20] precommit fixes --- robot.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/robot.py b/robot.py index 04a9f2f5..6bcb7e84 100644 --- a/robot.py +++ b/robot.py @@ -12,8 +12,6 @@ from utilities.game import is_red from utilities.scalers import rescale_js -from utilities.functions import clamp -from utilities.position import distance_between class MyRobot(magicbot.MagicRobot): From de7aafb124338106952e4b2bf358bf01dae20394 Mon Sep 17 00:00:00 2001 From: Beana1234 Date: Tue, 22 Oct 2024 19:56:58 +1100 Subject: [PATCH 10/20] fix pdm config --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 1260f854..543e8862 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,6 +55,7 @@ ignore = ["E501"] [tool.pdm] +distribution = false [project] name = "pyreefscape" version = "0.0.0" From 742b79eacdd423b057cfc703ae957ba6a8d25a94 Mon Sep 17 00:00:00 2001 From: Beana1234 Date: Tue, 22 Oct 2024 19:59:28 +1100 Subject: [PATCH 11/20] add physics file --- physics.py | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 physics.py diff --git a/physics.py b/physics.py new file mode 100644 index 00000000..581f6d1c --- /dev/null +++ b/physics.py @@ -0,0 +1,131 @@ +from __future__ import annotations + +import math +import typing + +import phoenix6 +import phoenix6.unmanaged +import wpilib +from pyfrc.physics.core import PhysicsInterface +from wpilib.simulation import DCMotorSim, SimDeviceSim +from wpimath.kinematics import SwerveDrive4Kinematics +from wpimath.system.plant import DCMotor +from wpimath.units import kilogram_square_meters + +from components.chassis import SwerveModule +from components.shooter import ShooterComponent + +if typing.TYPE_CHECKING: + from robot import MyRobot + + +class SimpleTalonFXMotorSim: + def __init__( + self, motor: phoenix6.hardware.TalonFX, units_per_rev: float, kV: float + ) -> None: + self.sim_state = motor.sim_state + self.sim_state.set_supply_voltage(12.0) + self.kV = kV # volt seconds per unit + self.units_per_rev = units_per_rev + + def update(self, dt: float) -> None: + voltage = self.sim_state.motor_voltage + velocity = voltage / self.kV # units per second + velocity_rps = velocity * self.units_per_rev + self.sim_state.set_rotor_velocity(velocity_rps) + self.sim_state.add_rotor_position(velocity_rps * dt) + + +class Falcon500MotorSim: + def __init__( + self, + *motors: phoenix6.hardware.TalonFX, + # Reduction between motor and encoder readings, as output over input. + # If the mechanism spins slower than the motor, this number should be greater than one. + gearing: float, + moi: kilogram_square_meters, + ): + self.gearing = gearing + self.sim_states = [motor.sim_state for motor in motors] + for sim_state in self.sim_states: + sim_state.set_supply_voltage(12.0) + self.motor_sim = DCMotorSim(DCMotor.falcon500(len(motors)), gearing, moi) + + def update(self, dt: float) -> None: + voltage = self.sim_states[0].motor_voltage + self.motor_sim.setInputVoltage(voltage) + self.motor_sim.update(dt) + motor_rev_per_mechanism_rad = self.gearing / math.tau + for sim_state in self.sim_states: + sim_state.set_raw_rotor_position( + self.motor_sim.getAngularPosition() * motor_rev_per_mechanism_rad + ) + sim_state.set_rotor_velocity( + self.motor_sim.getAngularVelocity() * motor_rev_per_mechanism_rad + ) + + +class PhysicsEngine: + def __init__(self, physics_controller: PhysicsInterface, robot: MyRobot): + self.physics_controller = physics_controller + + self.kinematics: SwerveDrive4Kinematics = robot.chassis.kinematics + self.swerve_modules: tuple[ + SwerveModule, SwerveModule, SwerveModule, SwerveModule + ] = robot.chassis.modules + + # Motors + self.wheels = [ + SimpleTalonFXMotorSim( + module.drive, + units_per_rev=1 / module.DRIVE_MOTOR_REV_TO_METRES, + kV=2.7, + ) + for module in robot.chassis.modules + ] + self.steer = [ + Falcon500MotorSim( + module.steer, + gearing=1 / module.STEER_GEAR_RATIO, + # measured from MKCad CAD + moi=0.0009972, + ) + for module in robot.chassis.modules + ] + + # TODO(davo): update CAD to include hex shaft and remeasure + single_roller_moi = 0.00041 # measured from CAD + self.flywheel = Falcon500MotorSim( + robot.shooter_component.flywheel_left, + gearing=ShooterComponent.FLYWHEEL_GEAR_RATIO, + moi=2 * single_roller_moi, + ) + + self.imu = SimDeviceSim("navX-Sensor", 4) + self.imu_yaw = self.imu.getDouble("Yaw") + + def update_sim(self, now: float, tm_diff: float) -> None: + # Enable the Phoenix6 simulated devices + # TODO: delete when phoenix6 integrates with wpilib + if wpilib.DriverStation.isEnabled(): + phoenix6.unmanaged.feed_enable(0.1) + + for wheel in self.wheels: + wheel.update(tm_diff) + for steer in self.steer: + steer.update(tm_diff) + + self.flywheel.update(tm_diff) + + speeds = self.kinematics.toChassisSpeeds( + ( + self.swerve_modules[0].get(), + self.swerve_modules[1].get(), + self.swerve_modules[2].get(), + self.swerve_modules[3].get(), + ) + ) + + self.imu_yaw.set(self.imu_yaw.get() - math.degrees(speeds.omega * tm_diff)) + + self.physics_controller.drive(speeds, tm_diff) From 00d04b4f39c298c5e07a7f1d0b6540074d9c3ff1 Mon Sep 17 00:00:00 2001 From: Beana1234 Date: Tue, 22 Oct 2024 20:03:32 +1100 Subject: [PATCH 12/20] fix physics file --- physics.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/physics.py b/physics.py index 581f6d1c..422ca085 100644 --- a/physics.py +++ b/physics.py @@ -13,7 +13,6 @@ from wpimath.units import kilogram_square_meters from components.chassis import SwerveModule -from components.shooter import ShooterComponent if typing.TYPE_CHECKING: from robot import MyRobot @@ -93,14 +92,6 @@ def __init__(self, physics_controller: PhysicsInterface, robot: MyRobot): for module in robot.chassis.modules ] - # TODO(davo): update CAD to include hex shaft and remeasure - single_roller_moi = 0.00041 # measured from CAD - self.flywheel = Falcon500MotorSim( - robot.shooter_component.flywheel_left, - gearing=ShooterComponent.FLYWHEEL_GEAR_RATIO, - moi=2 * single_roller_moi, - ) - self.imu = SimDeviceSim("navX-Sensor", 4) self.imu_yaw = self.imu.getDouble("Yaw") @@ -115,8 +106,6 @@ def update_sim(self, now: float, tm_diff: float) -> None: for steer in self.steer: steer.update(tm_diff) - self.flywheel.update(tm_diff) - speeds = self.kinematics.toChassisSpeeds( ( self.swerve_modules[0].get(), From b4a3dbd6208c6c8bc16b326fc03606beaa5d6a58 Mon Sep 17 00:00:00 2001 From: Beana1234 Date: Tue, 22 Oct 2024 20:33:07 +1100 Subject: [PATCH 13/20] second attempt at pdm install --- pdm.lock | 348 +++++++++++++++++++++++++++++++------------------ pyproject.toml | 28 +++- 2 files changed, 240 insertions(+), 136 deletions(-) diff --git a/pdm.lock b/pdm.lock index 67b8bf6f..bcc4603e 100644 --- a/pdm.lock +++ b/pdm.lock @@ -2,10 +2,10 @@ # It is not intended for manual editing. [metadata] -groups = ["default"] +groups = ["default", "dev", "typing"] strategy = ["inherit_metadata"] lock_version = "4.5.0" -content_hash = "sha256:356fe1fec85e30385f9adff0c0f3c9cb0d1e9f36b2e244cb76dd04e5ac71478c" +content_hash = "sha256:7cf3b9d2c8b3d59711521d817a49bf05a6f3c84442e9228f7ec10bee165a2fc8" [[metadata.targets]] requires_python = ">=3.10,<3.13" @@ -21,6 +21,20 @@ files = [ {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, ] +[[package]] +name = "attrs" +version = "24.2.0" +requires_python = ">=3.7" +summary = "Classes Without Boilerplate" +groups = ["dev"] +dependencies = [ + "importlib-metadata; python_version < \"3.8\"", +] +files = [ + {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, + {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, +] + [[package]] name = "bcrypt" version = "4.2.0" @@ -110,8 +124,8 @@ 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 = "(platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\") and sys_platform == \"win32\"" +groups = ["default", "dev"] +marker = "sys_platform == \"win32\"" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -158,8 +172,8 @@ name = "exceptiongroup" version = "1.2.2" requires_python = ">=3.7" summary = "Backport of PEP 654 (exception groups)" -groups = ["default"] -marker = "(platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\") and python_version < \"3.11\"" +groups = ["default", "dev"] +marker = "python_version < \"3.11\"" files = [ {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, @@ -195,18 +209,75 @@ files = [ {file = "flexparser-0.3.1.tar.gz", hash = "sha256:36f795d82e50f5c9ae2fde1c33f21f88922fdd67b7629550a3cc4d0b40a66856"}, ] +[[package]] +name = "hypothesis" +version = "6.115.3" +requires_python = ">=3.9" +summary = "A library for property-based testing" +groups = ["dev"] +dependencies = [ + "attrs>=22.2.0", + "exceptiongroup>=1.0.0; python_version < \"3.11\"", + "sortedcontainers<3.0.0,>=2.1.0", +] +files = [ + {file = "hypothesis-6.115.3-py3-none-any.whl", hash = "sha256:d2770b0db08ad666fe6ff36027910039ab681084d13bcf9c057449c2e27099c4"}, + {file = "hypothesis-6.115.3.tar.gz", hash = "sha256:d4efc8c7371bd4ec906d2777f1f18fee5539e47b3d7c7cdc93d1026ad35d9b33"}, +] + [[package]] name = "iniconfig" version = "2.0.0" requires_python = ">=3.7" summary = "brain-dead simple config-ini parsing" -groups = ["default"] -marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +groups = ["default", "dev"] files = [ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] +[[package]] +name = "mypy" +version = "1.12.1" +requires_python = ">=3.8" +summary = "Optional static typing for Python" +groups = ["typing"] +dependencies = [ + "mypy-extensions>=1.0.0", + "tomli>=1.1.0; python_version < \"3.11\"", + "typing-extensions>=4.6.0", +] +files = [ + {file = "mypy-1.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3d7d4371829184e22fda4015278fbfdef0327a4b955a483012bd2d423a788801"}, + {file = "mypy-1.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f59f1dfbf497d473201356966e353ef09d4daec48caeacc0254db8ef633a28a5"}, + {file = "mypy-1.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b947097fae68004b8328c55161ac9db7d3566abfef72d9d41b47a021c2fba6b1"}, + {file = "mypy-1.12.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:96af62050971c5241afb4701c15189ea9507db89ad07794a4ee7b4e092dc0627"}, + {file = "mypy-1.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:d90da248f4c2dba6c44ddcfea94bb361e491962f05f41990ff24dbd09969ce20"}, + {file = "mypy-1.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1230048fec1380faf240be6385e709c8570604d2d27ec6ca7e573e3bc09c3735"}, + {file = "mypy-1.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:02dcfe270c6ea13338210908f8cadc8d31af0f04cee8ca996438fe6a97b4ec66"}, + {file = "mypy-1.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a5a437c9102a6a252d9e3a63edc191a3aed5f2fcb786d614722ee3f4472e33f6"}, + {file = "mypy-1.12.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:186e0c8346efc027ee1f9acf5ca734425fc4f7dc2b60144f0fbe27cc19dc7931"}, + {file = "mypy-1.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:673ba1140a478b50e6d265c03391702fa11a5c5aff3f54d69a62a48da32cb811"}, + {file = "mypy-1.12.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9fb83a7be97c498176fb7486cafbb81decccaef1ac339d837c377b0ce3743a7f"}, + {file = "mypy-1.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:389e307e333879c571029d5b93932cf838b811d3f5395ed1ad05086b52148fb0"}, + {file = "mypy-1.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:94b2048a95a21f7a9ebc9fbd075a4fcd310410d078aa0228dbbad7f71335e042"}, + {file = "mypy-1.12.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ee5932370ccf7ebf83f79d1c157a5929d7ea36313027b0d70a488493dc1b179"}, + {file = "mypy-1.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:19bf51f87a295e7ab2894f1d8167622b063492d754e69c3c2fed6563268cb42a"}, + {file = "mypy-1.12.1-py3-none-any.whl", hash = "sha256:ce561a09e3bb9863ab77edf29ae3a50e65685ad74bba1431278185b7e5d5486e"}, + {file = "mypy-1.12.1.tar.gz", hash = "sha256:f5b3936f7a6d0e8280c9bdef94c7ce4847f5cdfc258fbb2c29a8c1711e8bb96d"}, +] + +[[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 = ["typing"] +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 = "1.26.4" @@ -246,8 +317,7 @@ name = "packaging" version = "23.2" requires_python = ">=3.7" summary = "Core utilities for Python packages" -groups = ["default"] -marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +groups = ["default", "dev"] files = [ {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, @@ -326,8 +396,7 @@ name = "pluggy" version = "1.5.0" requires_python = ">=3.8" summary = "plugin and hook calling mechanisms for python" -groups = ["default"] -marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +groups = ["default", "dev"] files = [ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, @@ -401,24 +470,24 @@ files = [ [[package]] name = "pyntcore" -version = "2024.3.2.0" +version = "2024.3.2.1" requires_python = ">=3.8" summary = "Binary wrappers for the FRC ntcore library" groups = ["default"] dependencies = [ - "robotpy-wpinet==2024.3.2.0", - "robotpy-wpiutil==2024.3.2.0", + "robotpy-wpinet==2024.3.2.1", + "robotpy-wpiutil==2024.3.2.1", ] files = [ - {file = "pyntcore-2024.3.2.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:34c0e34f28eaeb9ef3e096ba49b4cc48a5e663ebf6578ce9595ab0851a73a1de"}, - {file = "pyntcore-2024.3.2.0-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:615c960729c49ca0dccfd4b598ac1809637e13efbdbb995ec35837101d8ba342"}, - {file = "pyntcore-2024.3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:7c3ab86b83761787887eec530bdfacd3fb21c8deaf9edcf03ca1c3d33d87eb5d"}, - {file = "pyntcore-2024.3.2.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:55050ced774f897fbe79063f2b3f460ee60df348c7cf5141784a6f07b2b59ca6"}, - {file = "pyntcore-2024.3.2.0-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:da4f8bb3d1428de15bf265fe21e70e17c221b620df069c6a30d59431d7f70357"}, - {file = "pyntcore-2024.3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:355e6fc18b8a2bd2b3fb6467428f42bde1615444d2dc9ee96bbeb4ad8a5d0936"}, - {file = "pyntcore-2024.3.2.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:14d31540c29cdbc6bfbfc81b9b3e1535b91aec03bf012e42bb388a9ee450cca2"}, - {file = "pyntcore-2024.3.2.0-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:5f805578f476b725e32a8250af8bb953f526c1fa742e851d258757229cce07c8"}, - {file = "pyntcore-2024.3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:f4689b90e35b0630ca35b0803d7d2b4e993d9cc13073dc11e49c0823be5570fb"}, + {file = "pyntcore-2024.3.2.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:797f63318d74d6ac35377959963d96a5d7efdd8aab83bde53d8460d57187d081"}, + {file = "pyntcore-2024.3.2.1-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:bb004fd47cb421420b951d1b4f317459d92254b24622a126bf532c19c0f9bb04"}, + {file = "pyntcore-2024.3.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:141977ac2dd907bbbfc825cea714903b556f5bef6f85f2ee400c962a926b9fc1"}, + {file = "pyntcore-2024.3.2.1-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:e9b522da7779c648a3a0fb1c6825efe8a76df782ac3f0e1eba8df9327a09e9d8"}, + {file = "pyntcore-2024.3.2.1-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:74c872d24db91dd0e1c8e268fa55f806645cc1e9c013cc802b0d22dd0eb85e2a"}, + {file = "pyntcore-2024.3.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:9784b8944a276330d5c3a28d863ad73ce9751c15a3e1617ce7a8b7d42bc0f438"}, + {file = "pyntcore-2024.3.2.1-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:cd8e05bdcfb7f147f846553bb96a286aa479c436b5708b192d21da487643c706"}, + {file = "pyntcore-2024.3.2.1-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:125620969a399da9a90b1806c90aa46476dbcb8b9a2f079d888eb08da8f2057c"}, + {file = "pyntcore-2024.3.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:4c9bc823706a1245c62ba6b9eaf4ddf46e647bb00b8a540e29adb182bf3ad361"}, ] [[package]] @@ -426,8 +495,7 @@ name = "pytest" version = "8.3.3" requires_python = ">=3.8" summary = "pytest: simple powerful testing with Python" -groups = ["default"] -marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +groups = ["default", "dev"] dependencies = [ "colorama; sys_platform == \"win32\"", "exceptiongroup>=1.0.0rc8; python_version < \"3.11\"", @@ -441,6 +509,17 @@ files = [ {file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"}, ] +[[package]] +name = "pytest-integration" +version = "0.2.3" +requires_python = ">=3.6" +summary = "Organizing pytests by integration or not" +groups = ["dev"] +files = [ + {file = "pytest_integration-0.2.3-py3-none-any.whl", hash = "sha256:7f59ed1fa1cc8cb240f9495b68bc02c0421cce48589f78e49b7b842231604b12"}, + {file = "pytest_integration-0.2.3.tar.gz", hash = "sha256:b00988a5de8a6826af82d4c7a3485b43fbf32c11235e9f4a8b7225eef5fbcf65"}, +] + [[package]] name = "pytest-reraise" version = "2.1.2" @@ -458,48 +537,48 @@ files = [ [[package]] name = "robotpy" -version = "2024.3.2.1" -requires_python = ">=3.8,<3.13" +version = "2024.3.2.2" +requires_python = "<3.13,>=3.8" summary = "Meta package to make installing robotpy easier" groups = ["default"] dependencies = [ "pyfrc<2025.0.0,>=2024.0.0; platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"", - "pyntcore==2024.3.2.0", + "pyntcore==2024.3.2.1", "robotpy-cli<2025.0.0,>=2024.0.0", - "robotpy-hal==2024.3.2.0", - "robotpy-halsim-gui==2024.3.2.0; platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"", + "robotpy-hal==2024.3.2.1", + "robotpy-halsim-gui==2024.3.2.1; platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"", "robotpy-installer<2025.0.0,>=2024.2.0; platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"", "robotpy-wpilib-utilities<2025.0.0,>=2024.0.0", - "robotpy-wpimath==2024.3.2.0", - "robotpy-wpinet==2024.3.2.0", - "robotpy-wpiutil==2024.3.2.0", - "wpilib==2024.3.2.0", + "robotpy-wpimath==2024.3.2.1", + "robotpy-wpinet==2024.3.2.1", + "robotpy-wpiutil==2024.3.2.1", + "wpilib==2024.3.2.1", ] files = [ - {file = "robotpy-2024.3.2.1-py3-none-any.whl", hash = "sha256:ac4de7f1074f7a1483cd7ec7ee965408762bcbff7ab24df5001c4c5ed261be3d"}, - {file = "robotpy-2024.3.2.1.tar.gz", hash = "sha256:8fa2d54a94182d3fda8cf12df928d48237598d6c2e1624e0803a0589ce74c4cd"}, + {file = "robotpy-2024.3.2.2-py3-none-any.whl", hash = "sha256:9af5a6c0a28384e3bab11247f04231c6110d827561f61b39bfffffd4e8b14833"}, + {file = "robotpy-2024.3.2.2.tar.gz", hash = "sha256:7557934f08e149aa4af8cc67a2bc14ef70408e21833c6075222aaf040d2e9117"}, ] [[package]] name = "robotpy-apriltag" -version = "2024.3.2.0" +version = "2024.3.2.1" requires_python = ">=3.8" summary = "RobotPy bindings for WPILib's AprilTag library" groups = ["default"] dependencies = [ - "robotpy-wpimath==2024.3.2.0", - "robotpy-wpiutil==2024.3.2.0", + "robotpy-wpimath==2024.3.2.1", + "robotpy-wpiutil==2024.3.2.1", ] files = [ - {file = "robotpy_apriltag-2024.3.2.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:af969bf6ccfc0521ea90e12102598e3019036e44daae18b41ff38757163276d6"}, - {file = "robotpy_apriltag-2024.3.2.0-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:70deb648eab7a254899cc1e64f4686dd86d980499817f42decf139db0259ff68"}, - {file = "robotpy_apriltag-2024.3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:b73305c2fb6f39ec69f80cc86e4974084e958962e6ac471a0fde882bb6ec28c2"}, - {file = "robotpy_apriltag-2024.3.2.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:e3eaf91581758a4a221e39bc46b4d6a003f6b02cad8f606745273a33b5c6129e"}, - {file = "robotpy_apriltag-2024.3.2.0-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:91b18209e9978f5e6758dfea35ad67cb3946f8ea8b368addc58226df5c02bacf"}, - {file = "robotpy_apriltag-2024.3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:04b7b8d6384918c2fdaec740d979364d2adc764ed9787ca47a1ee54bcfb59b7e"}, - {file = "robotpy_apriltag-2024.3.2.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:df975a0a71bd3d6cac944aabd60992154c3c4452c5b1e5f6d4afaae2895ccddd"}, - {file = "robotpy_apriltag-2024.3.2.0-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:4ec49df16cb4de11755a54cde8a67737417f072e0f3db5ea6d3a527fc17a86bc"}, - {file = "robotpy_apriltag-2024.3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:0186d09e7b39d45e5c408a62a191ecafc22e8d9fe23be49ab5ec9f04acd72d23"}, + {file = "robotpy_apriltag-2024.3.2.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:e7471740f78303fd5b803fcb54cc7b060281e55de1c3778ce6a1997c509f4bb6"}, + {file = "robotpy_apriltag-2024.3.2.1-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:1ba06f039308857f8719c70f7796ae931070761e65c36d25b25411b85ec7e095"}, + {file = "robotpy_apriltag-2024.3.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:0d438b16cb1f3f8526601ebd9cb89d8307fe7cb4c86a9ccffba5dd4d803af9b0"}, + {file = "robotpy_apriltag-2024.3.2.1-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:099b8ff91532acad7fa0efeb398e7c2d882c4737dd350346c642cdb1ea489c62"}, + {file = "robotpy_apriltag-2024.3.2.1-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:e4d3e01a3ef86642043f911071d92475eed4cb240503f8744e02dee0d069c40f"}, + {file = "robotpy_apriltag-2024.3.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf26a5e1b8ac83931de7cd348360005d55004201ac4a3c8f218d9b2a2f1733ce"}, + {file = "robotpy_apriltag-2024.3.2.1-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:2e8d34326aa142c2d1490d8db1fc7b0ea5fdbe3866415f6e1586c8542aa02596"}, + {file = "robotpy_apriltag-2024.3.2.1-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:7a127a5b4c77f2894830c57e547f20da6004f617b8a45a9b62184611aa3491d8"}, + {file = "robotpy_apriltag-2024.3.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:f09bf89333aafa677949c59e60e2d2e40d10ae0e9662110d63216309b1e7434d"}, ] [[package]] @@ -515,48 +594,48 @@ files = [ [[package]] name = "robotpy-hal" -version = "2024.3.2.0" +version = "2024.3.2.1" requires_python = ">=3.8" summary = "Binary wrapper for FRC HAL" groups = ["default"] dependencies = [ - "robotpy-wpiutil==2024.3.2.0", + "robotpy-wpiutil==2024.3.2.1", ] files = [ - {file = "robotpy_hal-2024.3.2.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7f502f2e63afa843e58cff9ca122db715fd5cf5bb2d7b1af560eaa74594de3a9"}, - {file = "robotpy_hal-2024.3.2.0-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:f6da11a7e1619fa591cca78dfd866aaa5f46e03e7436c98f5ef98d71eaa97562"}, - {file = "robotpy_hal-2024.3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:2132d8fc81dce244191759333d4be8ac1143c5a2b5654a2bc877fee4f7a18b5e"}, - {file = "robotpy_hal-2024.3.2.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:4e4b605c219647402733e66532a142f2e71e37b78e3507cfb9e7c031eb5ffa0a"}, - {file = "robotpy_hal-2024.3.2.0-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:6367540610d4398bb6d81922d540c2665115e3167d9c263b4fb2aaf7364f4c5a"}, - {file = "robotpy_hal-2024.3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:f82d2ae057d86a59c4379f67b43fa304d999e90f6b3f84ff877abc16844d7d0e"}, - {file = "robotpy_hal-2024.3.2.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:714fb5b73eaf758b69a8a506f6ede60ca16d4036014eae383b2493f885d6cfd7"}, - {file = "robotpy_hal-2024.3.2.0-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:e02088620b2809000c85e2f8da9a6cc7a58592e5fa81b9b75d33e83e5dce8d2f"}, - {file = "robotpy_hal-2024.3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:8da8365f09e7cb2287d9b50e8ebe1a117f47f1cf7cf2c4ebe75146b4d6ec7189"}, + {file = "robotpy_hal-2024.3.2.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:2f002028dc3d5448c00ba5e1604f1707cc999dd325833f8650224ff999d15d16"}, + {file = "robotpy_hal-2024.3.2.1-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:d9a7035f6cfe23f609eaaf1c7d8557921f2890afcbb362f7707d71b1264c211a"}, + {file = "robotpy_hal-2024.3.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:e02d3b43c5017702e04ef3f3c5e5e1152558659975ac1b6440ab37be23d2a128"}, + {file = "robotpy_hal-2024.3.2.1-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:757806683309a19a2070ae1189d7e05c929cfdefd00c364123055e7a304aa7a5"}, + {file = "robotpy_hal-2024.3.2.1-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:2688317b981f2fe2d2abe07a60a800b8ca6f641d57e72d564ec25056b045010b"}, + {file = "robotpy_hal-2024.3.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:86705b5afb2f1f0b40a940fd004b237387147a4ca782b5b7792a53d297b3eddb"}, + {file = "robotpy_hal-2024.3.2.1-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:4c6e92860eeead1317aead29d6fd975198ee444575d6bfb28693bc6f62c5eafe"}, + {file = "robotpy_hal-2024.3.2.1-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:d8407e8922a4c74a6b215b90b5d8b1e3bd6578de1e816b5e143148a6d7ea7fb3"}, + {file = "robotpy_hal-2024.3.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:48df8115263c7bb94a6cfebd31c5aa07fb50b368eaeb72284629986e9f9cbdd9"}, ] [[package]] name = "robotpy-halsim-gui" -version = "2024.3.2.0" +version = "2024.3.2.1" requires_python = ">=3.8" summary = "WPILib command framework" groups = ["default"] marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" dependencies = [ - "pyntcore==2024.3.2.0", - "robotpy-hal==2024.3.2.0", - "robotpy-wpimath==2024.3.2.0", - "robotpy-wpiutil==2024.3.2.0", + "pyntcore==2024.3.2.1", + "robotpy-hal==2024.3.2.1", + "robotpy-wpimath==2024.3.2.1", + "robotpy-wpiutil==2024.3.2.1", ] files = [ - {file = "robotpy_halsim_gui-2024.3.2.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:ad048ce936c732c031600e41d19eac23f541ee5021f72daaf89a74e00c5b1ff7"}, - {file = "robotpy_halsim_gui-2024.3.2.0-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:ef94a2d1261aaa24cd6c74ac5a301b4b11ee377adeac8eebbf0a0a3dbadd8d2d"}, - {file = "robotpy_halsim_gui-2024.3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:50d8d8e576f24ebed2090824fbb48f5b1be7d435af78f907fe9f2ef8bbd63b32"}, - {file = "robotpy_halsim_gui-2024.3.2.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:009a81a524cbfa0e7de0756b1eeb50d64f908e16991c60507dd2b1c2feb20c2f"}, - {file = "robotpy_halsim_gui-2024.3.2.0-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:63a3a4926af23d1f3f9224490ffed605dca86ccf14294906871ff847d15c3c68"}, - {file = "robotpy_halsim_gui-2024.3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:2006162cb96fda821c5f94679168374de2fbeeb3d61150dda6cfe5ab33bb17e5"}, - {file = "robotpy_halsim_gui-2024.3.2.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:27ecfc05f54d48ecf228198daa6fb02ef9589d42efe08f40bd557d3066e1dc43"}, - {file = "robotpy_halsim_gui-2024.3.2.0-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:27804d6a0c32caafb9db82311e6b56fe9699b67e12fdcbdee921124a7b080c0a"}, - {file = "robotpy_halsim_gui-2024.3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:5d9f700239ef755da05d71910dc04daec74ac7cc11e61bd38b07ae02b382c24b"}, + {file = "robotpy_halsim_gui-2024.3.2.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:36eaf4693818ba306085a4e643fab4322bd407160e7c93b59bd5468114735d4c"}, + {file = "robotpy_halsim_gui-2024.3.2.1-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:d4b0e37a5d54cb89aa5612e1e48fceba9e9dfb67f8d5ca411b73741e029df10a"}, + {file = "robotpy_halsim_gui-2024.3.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:56dd7d5918e086d3ba9d75ec7c33f3ecf910203bf7a5d3c276c2bf0e1298c72c"}, + {file = "robotpy_halsim_gui-2024.3.2.1-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:9e112409734650d81aa98ba2bc372234e8d62476b0e6ef661f4d967c73903d3f"}, + {file = "robotpy_halsim_gui-2024.3.2.1-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:6319fc2f191cf0175f30d6c6fde6f8a8b3ba3eee3deaf66fe1901f0ed7ed0697"}, + {file = "robotpy_halsim_gui-2024.3.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:8238d42d840e15e9cefff4658c2fdea0147236c6c288a35ff34439d19c75faad"}, + {file = "robotpy_halsim_gui-2024.3.2.1-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:21a63213972ae93a0c35619992f1b630fbd9fdd7a16516784e17ef606e6b8ab1"}, + {file = "robotpy_halsim_gui-2024.3.2.1-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:e7cc034fd45a45f816d7ce89b89c44155d01f65067ab76228d1e84ad0b78b93f"}, + {file = "robotpy_halsim_gui-2024.3.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:c123ef38c3da72a4b8472bab124198ad01826eca419a8040103bb1b9bce32324"}, ] [[package]] @@ -629,76 +708,76 @@ files = [ [[package]] name = "robotpy-wpilib-utilities" -version = "2024.0.0" +version = "2024.1.0" requires_python = ">=3.8" summary = "Useful utility functions/objects for RobotPy" groups = ["default"] dependencies = [ - "wpilib<2025,>=2024.1.1.0", + "wpilib<2025,>=2024.3.2.1", ] files = [ - {file = "robotpy-wpilib-utilities-2024.0.0.tar.gz", hash = "sha256:f2e7e512e3e9ad938893175b22c827f97d0866ade47f34c25d68622c3f8a4c3a"}, - {file = "robotpy_wpilib_utilities-2024.0.0-py3-none-any.whl", hash = "sha256:da0d3495d28b8f758c0bc12f1075996273aae831c5dd9d85d6b0581f8f08bcaa"}, + {file = "robotpy_wpilib_utilities-2024.1.0-py3-none-any.whl", hash = "sha256:6dbbdba6a31d8cc3e293042c401831c8eec91b90de71263ab0eafb83f38ace28"}, + {file = "robotpy_wpilib_utilities-2024.1.0.tar.gz", hash = "sha256:3888f7f75b645fce464a547b30c3b8d1714c8be16b2a7667cab99c5b47b93cc5"}, ] [[package]] name = "robotpy-wpimath" -version = "2024.3.2.0" +version = "2024.3.2.1" requires_python = ">=3.8" summary = "Binary wrapper for FRC WPIMath library" groups = ["default"] dependencies = [ - "robotpy-wpiutil==2024.3.2.0", + "robotpy-wpiutil==2024.3.2.1", ] files = [ - {file = "robotpy_wpimath-2024.3.2.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:b2d5f852c734b53fab279532a0ac47cb9570036208543a01cbd10aeb3a73fa70"}, - {file = "robotpy_wpimath-2024.3.2.0-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:e7b3b8759d1c791c95f8a62199f4038c4c485b85e0cb160d4c93120591795269"}, - {file = "robotpy_wpimath-2024.3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:6813e4a22b9463410eb5bcd7c838a04ef1fd59c3590ef21176c7c1d7c74bb5cc"}, - {file = "robotpy_wpimath-2024.3.2.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:e2b2670939545b80afd85692031e86f2a53da5b5ecdf97baaa96cb687067294f"}, - {file = "robotpy_wpimath-2024.3.2.0-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:0844991c6c84747f32274628d3eb15f7082458090fed015fe4f7dbd08fcbdb4c"}, - {file = "robotpy_wpimath-2024.3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:fbc80e929cba60d25208d167f573a1151a8f8851a66a670fe464ef0c53fee76a"}, - {file = "robotpy_wpimath-2024.3.2.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:2f0c4168f128bef603b55cf926cedad27eed0a98824a4fe244de51db48e0d05d"}, - {file = "robotpy_wpimath-2024.3.2.0-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:a474951a3dcf80154aad597d46eb26de7e485145228e8e2892a0adc3cc98e3fd"}, - {file = "robotpy_wpimath-2024.3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:abd2a365a5edd9f6caca56540a48256549cedef490f3286274443fd9a8f703e6"}, + {file = "robotpy_wpimath-2024.3.2.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:4501f3ef95d18ab044001e339c14aec3260dc58c0dded9c963ceda045ccb7883"}, + {file = "robotpy_wpimath-2024.3.2.1-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:95dc21baa6beb0264fb3489de850fce4578ecbc4f661a8098439bb70bc96f3a6"}, + {file = "robotpy_wpimath-2024.3.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:283f795cf6393b6ca0c5797b16ae36fd149b3f2494418c5bb1cbb1571c594d17"}, + {file = "robotpy_wpimath-2024.3.2.1-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:a173cdce96691cf87f172b1455b6128bbf410f01f7940b3e1afc3373447e0365"}, + {file = "robotpy_wpimath-2024.3.2.1-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:8d46645499c470306c3665f3ecd2124fdcf141c4ae48cb25b01e4231dce3c70a"}, + {file = "robotpy_wpimath-2024.3.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:cdea57f90bb04039c8e2f5f265460c61ba18fd742ed01a3b34bcf160f1e8f323"}, + {file = "robotpy_wpimath-2024.3.2.1-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:ced2ce07dae855f4526dc8fa920b372a67e2fa286f2ccaf66786b82d039fb967"}, + {file = "robotpy_wpimath-2024.3.2.1-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:38bd81647483afa0bec474ab5a0915aa5b63a2c2fffa093188bf1c593a873119"}, + {file = "robotpy_wpimath-2024.3.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:ea8aea67dc9976c3ac103a794623a43e2d8364d76791ecd5aad2d0eb9faab24d"}, ] [[package]] name = "robotpy-wpinet" -version = "2024.3.2.0" +version = "2024.3.2.1" requires_python = ">=3.8" summary = "Binary wrapper for FRC wpinet library" groups = ["default"] dependencies = [ - "robotpy-wpiutil==2024.3.2.0", + "robotpy-wpiutil==2024.3.2.1", ] files = [ - {file = "robotpy_wpinet-2024.3.2.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:132906e671d3bb1e1775817ecf3fa375e8f95a2ad11288ad7fec8a3b47c21685"}, - {file = "robotpy_wpinet-2024.3.2.0-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:05f52054c46f41e1f5e98601cb9699e5975874b5fd8a7b65bf21437a10df262c"}, - {file = "robotpy_wpinet-2024.3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:64a0cbbe5cb9e043e06f66e9388cff1a3f057f4150232629e93ab7b71c4366ff"}, - {file = "robotpy_wpinet-2024.3.2.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:93de7c9fe78fb095c8f83921c1a37b3ab045e7108b0951b45802f1e6690db8bb"}, - {file = "robotpy_wpinet-2024.3.2.0-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:844fae2241f60b9ed53bbc292f2e36ae513f9bb2c30b46a7a7547ab257a3c40c"}, - {file = "robotpy_wpinet-2024.3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:61536f024ab59a4ad56cb88608708188590b90307436eef87dda465ddf59553e"}, - {file = "robotpy_wpinet-2024.3.2.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:45f5e0459f41b8ff5bd1c323fb3d969bddfdaf7d34f36c995d57e7216743a882"}, - {file = "robotpy_wpinet-2024.3.2.0-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:92a5e27678065adc4d0ff008527772fd58d5e31ccf57a77d2a899219be8193eb"}, - {file = "robotpy_wpinet-2024.3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:802e398e55a5c9e1f7a60b425b169b2acb08c0c5d45dcd34e6bb5a1253455094"}, + {file = "robotpy_wpinet-2024.3.2.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:ce0284d78e2219fe8108e792eaff994b5af162f2afc10072cd63da733bb6d519"}, + {file = "robotpy_wpinet-2024.3.2.1-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:63b8d1098a8ee147c292e4cfed271c78b7749b087fe445ccfe038778c23812aa"}, + {file = "robotpy_wpinet-2024.3.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:68c132a5e8f674310f3d2d53224c3045d5e2d0f4cff77ed9223fd422a6d548a8"}, + {file = "robotpy_wpinet-2024.3.2.1-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:127aaf05fa3e846581f63c347ca62df1a1cd0a831e8d73865e16570143f1d70f"}, + {file = "robotpy_wpinet-2024.3.2.1-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:718826ad336437ce6bc4e833326390a977bd56d00f22012fae3bb8da03464a96"}, + {file = "robotpy_wpinet-2024.3.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:5af246cc8063256df73575778b88d0141fe60b0b42fc6c11b7791934c3155fc1"}, + {file = "robotpy_wpinet-2024.3.2.1-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:c4b3bfd3452fe8f571924fedfc2cc11d61b3d2a6df897e8fd0014800e1db47aa"}, + {file = "robotpy_wpinet-2024.3.2.1-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:78fa34db28343bd8e081cbe3c981b00b2a0c7682cfc052bad2152777e06ab305"}, + {file = "robotpy_wpinet-2024.3.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:88d377af878062c94cd95b1e262879365119282e55ca9fa5b87d316201767688"}, ] [[package]] name = "robotpy-wpiutil" -version = "2024.3.2.0" +version = "2024.3.2.1" requires_python = ">=3.8" summary = "Binary wrapper for FRC WPIUtil library" groups = ["default"] files = [ - {file = "robotpy_wpiutil-2024.3.2.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:bf115575d856695481d07d397d3a12e035e71b2b1cbcaac89a8b66b2e855da05"}, - {file = "robotpy_wpiutil-2024.3.2.0-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:f007c94290cebffae26df1ed883e6e7b4320974e99e665561bce8db5ebf1230b"}, - {file = "robotpy_wpiutil-2024.3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:0780127251fbce6542a67951e517b0c453153d53b42480e678cc9182e9879674"}, - {file = "robotpy_wpiutil-2024.3.2.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:ccf9f3fbc0e4ea3e7d645bfab9dd5c1f2de7c8f5a01a75d6bd2c37f534e2e855"}, - {file = "robotpy_wpiutil-2024.3.2.0-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:f3cbbe94443018dccf471b57c270823544c923d2b10b374b6e74e935153baf86"}, - {file = "robotpy_wpiutil-2024.3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:b83f70b378817de29f122f8e5014f612bd72eb83c01e1d37065334e682e8a967"}, - {file = "robotpy_wpiutil-2024.3.2.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:e7c909fcf28e3d94f70adce57f897e47320edf5bcc45aa3956ce736bd6bc50cc"}, - {file = "robotpy_wpiutil-2024.3.2.0-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:ab5c4b9a06f462200fc67d7aaa0854b227c98be9d4bfbdfb929d787b72642a88"}, - {file = "robotpy_wpiutil-2024.3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:4972f2acfae01c0290c057031918dc9bd8c62f6b5c60addaccb2f3e6ad1d3dd0"}, + {file = "robotpy_wpiutil-2024.3.2.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:cccd8142a9e3cff7be3fbc18d91016af1a9e9acc00a7d0f4cbafa55a606106e6"}, + {file = "robotpy_wpiutil-2024.3.2.1-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:db2a7fe323fdbe27e7cd9c6f6b381913bb0b7c7694281509602c41dae3f77230"}, + {file = "robotpy_wpiutil-2024.3.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:43b46ca013aa94130418cdb13ee73634627c9b738b8e70e26598d9aea98aa76d"}, + {file = "robotpy_wpiutil-2024.3.2.1-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:c9f721682b364141eb5085129ba13789f10009876d7221e08faff889c487d244"}, + {file = "robotpy_wpiutil-2024.3.2.1-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:ee451802ca859766d84ca694cfbd93be9989ca5b6e0c2ab01b47a2e2dbdab5d0"}, + {file = "robotpy_wpiutil-2024.3.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:219df24e22b11bd3792e5a7f41b0c3333aaa219f79c517e5c2b82c86d5430c13"}, + {file = "robotpy_wpiutil-2024.3.2.1-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:f0b8aca37ab565244f27623647cce2adf08d0062bf225655c5a5a94daaf33b50"}, + {file = "robotpy_wpiutil-2024.3.2.1-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:d075c37a7c49386137b6c95d0ea33a47f42bcdf058b7380b6a1f4a0853b6af39"}, + {file = "robotpy_wpiutil-2024.3.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:ba74db179ca6f8a14fbe78df6144535b8811c9eac78dd183f5e60b94c4f02739"}, ] [[package]] @@ -712,13 +791,23 @@ files = [ {file = "setuptools-75.2.0.tar.gz", hash = "sha256:753bb6ebf1f465a1912e19ed1d41f403a79173a9acf66a42e7e6aec45c3c16ec"}, ] +[[package]] +name = "sortedcontainers" +version = "2.4.0" +summary = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +groups = ["dev"] +files = [ + {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, + {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, +] + [[package]] name = "tomli" version = "2.0.2" requires_python = ">=3.8" summary = "A lil' TOML parser" -groups = ["default"] -marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +groups = ["default", "dev", "typing"] +marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\" or python_version < \"3.11\"" files = [ {file = "tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38"}, {file = "tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"}, @@ -741,8 +830,7 @@ name = "typing-extensions" version = "4.12.2" requires_python = ">=3.8" summary = "Backported and Experimental Type Hints for Python 3.8+" -groups = ["default"] -marker = "platform_machine != \"roborio\" and platform_machine != \"armv7l\" and platform_machine != \"aarch64\"" +groups = ["default", "typing"] files = [ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, @@ -750,25 +838,25 @@ files = [ [[package]] name = "wpilib" -version = "2024.3.2.0" +version = "2024.3.2.1" requires_python = ">=3.8" summary = "Binary wrapper for FRC WPILib" groups = ["default"] dependencies = [ - "pyntcore==2024.3.2.0", + "pyntcore==2024.3.2.1", "robotpy-cli~=2024.0b", - "robotpy-hal==2024.3.2.0", - "robotpy-wpimath==2024.3.2.0", - "robotpy-wpiutil==2024.3.2.0", -] -files = [ - {file = "wpilib-2024.3.2.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:0703d5e4f3f1be08bd2aac3324894ea3983be0c20b6f3fdd9949ffbd9b12f4bd"}, - {file = "wpilib-2024.3.2.0-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:2c596589a7be0d10374a5ad4e652495214df4a7e7e24536dfb43dc1312ccfc7f"}, - {file = "wpilib-2024.3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:fa7e3534533097da5de558b4e457c5e1e9a7f4ca3d1d3aa4b9b28b127b1cc85c"}, - {file = "wpilib-2024.3.2.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:c1b71d890a6696d89fef865651f1d1db2fcd9160829bc94210d95bbc6f821651"}, - {file = "wpilib-2024.3.2.0-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:d00e32ebaf7b256507c6852fda37ddd7cf66ce0759304c66596b71d8888aad93"}, - {file = "wpilib-2024.3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:957a6737075dbcc185506e1f235ec647e67a309cb5f44a52e0106062f6d5b5a8"}, - {file = "wpilib-2024.3.2.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:fcc7abfef7a5961bc3a5f3846c74a3c9a951879f0dec53084e2757e54e70b0c7"}, - {file = "wpilib-2024.3.2.0-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:70d9f5ab97cf604e144e9e4e782306cca41b90869da0ae598f01d5b6fa88b11d"}, - {file = "wpilib-2024.3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:09eae37ee6dfcfa116f4fcf7c43a86e7ac4c4e8d1a3070fb67f8ab56862386d0"}, + "robotpy-hal==2024.3.2.1", + "robotpy-wpimath==2024.3.2.1", + "robotpy-wpiutil==2024.3.2.1", +] +files = [ + {file = "wpilib-2024.3.2.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:93719654e8c259bded07b44b392de108fc1f264ae646e2bd55636cfda31e04a6"}, + {file = "wpilib-2024.3.2.1-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:68a44888f2b850ff76a5cdbd48541f7a4cafabe413e2758a871c4000d11df463"}, + {file = "wpilib-2024.3.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:169f109c1f0d919514eed61c8eeb00930ed36a8b95886b943d75b2ca67520e09"}, + {file = "wpilib-2024.3.2.1-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:e8656a0de2526cfa9208ea8b3ae151147725ca993cee2a3ed00a669ab34369d4"}, + {file = "wpilib-2024.3.2.1-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:4b6d757d40beae32e5ff38a2468b0b777e40b3446ed201febebf6b29c3c21e47"}, + {file = "wpilib-2024.3.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:0e36b6666c4259285affc703da625ceb4225cdc1ddf6053a56cb295ebb60f715"}, + {file = "wpilib-2024.3.2.1-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:6c99fbe03f81bd08c5832dfd7102cf2a48a976a75d6ce713e1031a1b5df0063e"}, + {file = "wpilib-2024.3.2.1-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:33b901f8da1af0cdf3f8a6d08ca2d1db922ec5175d9ee16ee4b67f5b0788cec2"}, + {file = "wpilib-2024.3.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:f385c3474b4c49594ceee60acb781c507dea7a469b1bdabdb1607ba8ecbbbbd7"}, ] diff --git a/pyproject.toml b/pyproject.toml index 543e8862..6bd2461d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,9 +53,25 @@ select = [ ] ignore = ["E501"] - [tool.pdm] -distribution = false +package-type = "application" + +[tool.pdm.scripts] +deploy = "robotpy deploy" +download = "robotpy sync --no-install" +sim = "robotpy sim" +test = "robotpy test --" + +[tool.pdm.dev-dependencies] +dev = [ + "hypothesis", + "pytest>=7.2.0", + "pytest-integration>=0.2.3", +] +typing = [ + "mypy>=1.8.0", +] + [project] name = "pyreefscape" version = "0.0.0" @@ -71,11 +87,11 @@ dependencies = [ "numpy~=1.25", "phoenix6~=24.2.0", # robotpy[apriltag] pins numpy to a version that doesn't build cleanly on Python 3.12. - "robotpy==2024.3.2.1", + "robotpy==2024.3.2.2", "robotpy-apriltag~=2024.3.2", "robotpy-navx==2024.1.1", "robotpy-rev~=2024.2.4", - "robotpy-wpilib-utilities==2024.0.0", + "robotpy-wpilib-utilities==2024.1.0", "photonlibpy==2024.3.1", ] @@ -85,8 +101,8 @@ requires = [ "phoenix6~=24.2.0", "robotpy-navx==2024.1.1", "robotpy-rev~=2024.2.4", - "robotpy-wpilib-utilities==2024.0.0", + "robotpy-wpilib-utilities==2024.1.0", "photonlibpy==2024.3.1", ] -robotpy_version = "2024.3.2.1" +robotpy_version = "2024.3.2.2" robotpy_extras = ["apriltag"] From 748eb3a245383d44e9ef40ea170bc5b56f6d5be4 Mon Sep 17 00:00:00 2001 From: Beana1234 Date: Tue, 22 Oct 2024 20:35:18 +1100 Subject: [PATCH 14/20] delete led tests --- tests/test_led.py | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 tests/test_led.py diff --git a/tests/test_led.py b/tests/test_led.py deleted file mode 100644 index 8518c86f..00000000 --- a/tests/test_led.py +++ /dev/null @@ -1,6 +0,0 @@ -from components import led - - -def test_morse_messages_are_valid() -> None: - for message in led.Morse.MESSAGES: - led.Morse.translate_message(message) From 32a667dd6c188ffda6fe000b025544e264f550ee Mon Sep 17 00:00:00 2001 From: Beana1234 Date: Tue, 22 Oct 2024 20:36:05 +1100 Subject: [PATCH 15/20] remove junk files --- ...autonomous_test.cpython-312-pytest-8.0.0.pyc | Bin 1206 -> 0 bytes .../fuzz_test.cpython-312-pytest-8.0.0.pyc | Bin 8754 -> 0 bytes .../pyfrc_test.cpython-312-pytest-8.0.0.pyc | Bin 386 -> 0 bytes ...constrain_angle.cpython-312-pytest-8.0.0.pyc | Bin 15122 -> 0 bytes .../test_functions.cpython-312-pytest-8.0.0.pyc | Bin 10822 -> 0 bytes .../test_led.cpython-312-pytest-8.0.0.pyc | Bin 665 -> 0 bytes .../test_scalers.cpython-312-pytest-8.0.0.pyc | Bin 11930 -> 0 bytes .../CANCoder vers. H - 01 - 0 - ext.dat | Bin 2048 -> 0 bytes .../CANCoder vers. H - 02 - 0 - ext.dat | Bin 2048 -> 0 bytes .../CANCoder vers. H - 03 - 0 - ext.dat | Bin 2048 -> 0 bytes .../CANCoder vers. H - 04 - 0 - ext.dat | Bin 2048 -> 0 bytes .../Talon FX vers. C - 01 - 0 - ext.dat | Bin 2048 -> 0 bytes .../Talon FX vers. C - 010 - 0 - ext.dat | Bin 2048 -> 0 bytes .../Talon FX vers. C - 011 - 0 - ext.dat | Bin 2048 -> 0 bytes .../Talon FX vers. C - 02 - 0 - ext.dat | Bin 2048 -> 0 bytes .../Talon FX vers. C - 03 - 0 - ext.dat | Bin 2048 -> 0 bytes .../Talon FX vers. C - 04 - 0 - ext.dat | Bin 2048 -> 0 bytes .../Talon FX vers. C - 05 - 0 - ext.dat | Bin 2048 -> 0 bytes .../Talon FX vers. C - 06 - 0 - ext.dat | Bin 2048 -> 0 bytes .../Talon FX vers. C - 07 - 0 - ext.dat | Bin 2048 -> 0 bytes .../Talon FX vers. C - 08 - 0 - ext.dat | Bin 2048 -> 0 bytes .../Talon FX vers. C - 09 - 0 - ext.dat | Bin 2048 -> 0 bytes tests/logs/FRC_20240519_053213.wpilog | Bin 18698 -> 0 bytes tests/logs/FRC_20240519_054824.wpilog | Bin 18613 -> 0 bytes tests/logs/FRC_20240519_063231.wpilog | Bin 17776 -> 0 bytes tests/logs/FRC_20240519_063410.wpilog | Bin 18696 -> 0 bytes tests/logs/FRC_20240617_084719.wpilog | Bin 18667 -> 0 bytes tests/logs/FRC_20240617_084856.wpilog | Bin 18642 -> 0 bytes tests/logs/FRC_20240617_085013.wpilog | Bin 18627 -> 0 bytes tests/logs/FRC_20240617_085116.wpilog | Bin 18695 -> 0 bytes tests/logs/FRC_20240617_090306.wpilog | Bin 18654 -> 0 bytes tests/logs/FRC_20240618_075839.wpilog | Bin 18725 -> 0 bytes tests/logs/FRC_20240622_005426.wpilog | Bin 18656 -> 0 bytes tests/logs/FRC_20240622_010544.wpilog | Bin 17939 -> 0 bytes tests/logs/FRC_20240622_062328.wpilog | Bin 18640 -> 0 bytes tests/logs/FRC_TBD_4993bfc6c3d9d8b3.wpilog | Bin 4515 -> 0 bytes 36 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tests/__pycache__/autonomous_test.cpython-312-pytest-8.0.0.pyc delete mode 100644 tests/__pycache__/fuzz_test.cpython-312-pytest-8.0.0.pyc delete mode 100644 tests/__pycache__/pyfrc_test.cpython-312-pytest-8.0.0.pyc delete mode 100644 tests/__pycache__/test_constrain_angle.cpython-312-pytest-8.0.0.pyc delete mode 100644 tests/__pycache__/test_functions.cpython-312-pytest-8.0.0.pyc delete mode 100644 tests/__pycache__/test_led.cpython-312-pytest-8.0.0.pyc delete mode 100644 tests/__pycache__/test_scalers.cpython-312-pytest-8.0.0.pyc delete mode 100644 tests/ctre_sim/CANCoder vers. H - 01 - 0 - ext.dat delete mode 100644 tests/ctre_sim/CANCoder vers. H - 02 - 0 - ext.dat delete mode 100644 tests/ctre_sim/CANCoder vers. H - 03 - 0 - ext.dat delete mode 100644 tests/ctre_sim/CANCoder vers. H - 04 - 0 - ext.dat delete mode 100644 tests/ctre_sim/Talon FX vers. C - 01 - 0 - ext.dat delete mode 100644 tests/ctre_sim/Talon FX vers. C - 010 - 0 - ext.dat delete mode 100644 tests/ctre_sim/Talon FX vers. C - 011 - 0 - ext.dat delete mode 100644 tests/ctre_sim/Talon FX vers. C - 02 - 0 - ext.dat delete mode 100644 tests/ctre_sim/Talon FX vers. C - 03 - 0 - ext.dat delete mode 100644 tests/ctre_sim/Talon FX vers. C - 04 - 0 - ext.dat delete mode 100644 tests/ctre_sim/Talon FX vers. C - 05 - 0 - ext.dat delete mode 100644 tests/ctre_sim/Talon FX vers. C - 06 - 0 - ext.dat delete mode 100644 tests/ctre_sim/Talon FX vers. C - 07 - 0 - ext.dat delete mode 100644 tests/ctre_sim/Talon FX vers. C - 08 - 0 - ext.dat delete mode 100644 tests/ctre_sim/Talon FX vers. C - 09 - 0 - ext.dat delete mode 100644 tests/logs/FRC_20240519_053213.wpilog delete mode 100644 tests/logs/FRC_20240519_054824.wpilog delete mode 100644 tests/logs/FRC_20240519_063231.wpilog delete mode 100644 tests/logs/FRC_20240519_063410.wpilog delete mode 100644 tests/logs/FRC_20240617_084719.wpilog delete mode 100644 tests/logs/FRC_20240617_084856.wpilog delete mode 100644 tests/logs/FRC_20240617_085013.wpilog delete mode 100644 tests/logs/FRC_20240617_085116.wpilog delete mode 100644 tests/logs/FRC_20240617_090306.wpilog delete mode 100644 tests/logs/FRC_20240618_075839.wpilog delete mode 100644 tests/logs/FRC_20240622_005426.wpilog delete mode 100644 tests/logs/FRC_20240622_010544.wpilog delete mode 100644 tests/logs/FRC_20240622_062328.wpilog delete mode 100644 tests/logs/FRC_TBD_4993bfc6c3d9d8b3.wpilog diff --git a/tests/__pycache__/autonomous_test.cpython-312-pytest-8.0.0.pyc b/tests/__pycache__/autonomous_test.cpython-312-pytest-8.0.0.pyc deleted file mode 100644 index 77bd79175659af1bcca7a4ccafd01d2086ccc4d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1206 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 diff --git a/tests/__pycache__/pyfrc_test.cpython-312-pytest-8.0.0.pyc b/tests/__pycache__/pyfrc_test.cpython-312-pytest-8.0.0.pyc deleted file mode 100644 index dd92e27c100fa87b993fa6104d1f41bbf9309358..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 386 zcmX|5Jxjzu5Z&FJCif*a3U;<>4mqquL^v&M>}*0{$t8Oj++^3;J!DJ4|KJa>^0)X8 zwzUwugDZryaT3f8%*T7fym=qv@ql2wJ>D#Sv41w83-&*(r#QTlf)rGegtnbkLCz?t zddUuLHcakTVG>qR5+Pa>Pf%Ln`&-I~9XG(^_C*GMsNDkcNdpZ8=m&aO ze8_nwCFk#C-I&~5&(6|2)HZ2m?ggY*!aP`|(-{bpi@H$9)063Gs$Jd@X)B2g%JbHo ocAMzDQpHk=3)n|hifIn9tO82u7a=d?hXjmMKV~U)qyPW_ diff --git a/tests/__pycache__/test_constrain_angle.cpython-312-pytest-8.0.0.pyc b/tests/__pycache__/test_constrain_angle.cpython-312-pytest-8.0.0.pyc deleted file mode 100644 index d83da9ef882f126de1bdb7ffd64c079ca6a7c8a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15122 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 diff --git a/tests/__pycache__/test_functions.cpython-312-pytest-8.0.0.pyc b/tests/__pycache__/test_functions.cpython-312-pytest-8.0.0.pyc deleted file mode 100644 index cd295db5d0074415726926feefff40cd9beeefdf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10822 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 diff --git a/tests/__pycache__/test_scalers.cpython-312-pytest-8.0.0.pyc b/tests/__pycache__/test_scalers.cpython-312-pytest-8.0.0.pyc deleted file mode 100644 index 0269cbd988bd8fcff25741a472789f6e907910d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11930 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 Ab^rhX diff --git a/tests/ctre_sim/CANCoder vers. H - 01 - 0 - ext.dat b/tests/ctre_sim/CANCoder vers. H - 01 - 0 - ext.dat deleted file mode 100644 index f5436a83c92c277938a98c6dd2e2eec193c97344..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2048 zcmcIkPe@c@5FdA!+)86HVhxR45VM;I*@oc0)NrFqAY`b=ty95*7ZE`T!9{~aJn6+l zxg??$3rQFEAan^bFIERL?9`z{hh#OZH{Z!0u7d^5k9-*0BV=Mo+NsSUro zPBa{YQV^E|*w3_es;zq5;W_|C(ItoJ|1~x5pD8I?(z9ThqWhsEAd=$|1e?lV^nWSLVl^d{pwEp1)rOx(C4|b z=i(OUA$6ri^b>xGgD+bqKKgW+R1ZG-DO1J?1sZxAdq->$;N>L$9l$w_aq92uGS
XSI~hs!lj`GKd@he1C4lenmTzSEk{nEPX+`{u3elSudjHpX~9FYhfMXAk@1JHMmF z7yI1k2pEX}aNIdM-~IEAUxd#=3N9~BZ1nIxw!#u#E-myIF104|>(^gSn(txm>Aecp zZ0Mfu=6cyS(XE{HlT{uoAbiQ3?BVV|_+?Mh2kPT>qL2N6Z)36P=D-zO_h*%P_mJ{d zUc1=A{RVZeHH||b_1v%NTkA0ot8<)B*iLfuvBC9B z!TaRD2hWiDKJuM_>KAKx7bRB%zRtGaW*+wWBp-^tRdv?PD^Vi( g876v^kbKJq_}%Bfi;p~7kv%cD;Zz^}=6*^3U#-pyiU0rr diff --git a/tests/ctre_sim/CANCoder vers. H - 02 - 0 - ext.dat b/tests/ctre_sim/CANCoder vers. H - 02 - 0 - ext.dat deleted file mode 100644 index 69048972b816c38a976ce3338d18839ce0efee7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2048 zcmcIkPe{{o6n}2R7Ojv-R-&bsTF_w#)gp2~wQwDRz{s#2I*bm9GU%X5(g>jyf)btb zT*C^j7$sfYLF$-_u)36@x1eJ~4eR&5?|s&OKU^MK-^1STz0c=;-k)^fUAdy5n<)PJip+)K%UGh4GN8~vC5-_q&LJyn(K=MA-N1}dl*)7HvK zCKdnXI$gt~%jK{@?-tXOD3j zxY=c_OLx{Iaqv^Sl_xR;Jgq(q`0(BT$%#T+CTqYEQ}^8m*(Z_c`)rKyQeEC#Db61D z$IpC^7C+eMT!+s<{KN6$(fO_)X#OgCMa1#&vO0g2_pua|@bnI+|KdnnqBMWu)kE_> z4EEjF%QeH@kGnbFuc{Z;q@SGXSU%B9uE`#*{6$~(BtpoK9hUmo5A^brC(aKZCkov< zXzsm6b@!h-)WQAwb*?#$qdxMvU+x?En1`!#oKMgu0f#Z9NLdEx&C99$0! diff --git a/tests/ctre_sim/CANCoder vers. H - 03 - 0 - ext.dat b/tests/ctre_sim/CANCoder vers. H - 03 - 0 - ext.dat deleted file mode 100644 index ef7f6c0a7bba48a9966b765d4d54ecefdde98915..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2048 zcmcIkJ!n%=6h2L!THC5clvYvtT&&;{0!kfhUh7ZdCRA*#861LJG~!?p!5{^r2u5+z zSqmy!C2Dc$6N*2Ru?VS)iRk7Jx)?0dde1%gi@Bk3(0GS;-ue5!^K;)L`v2!?@>U;F zIs&Gpc(J8ts|#z>6fUp(xK_vROO0$_II6MMf2scg_06?3HLjkA)H~PKK)jeKtsZ2` z_~&cR;OND7v!{v98`-!HZKN+9!4Eykl!;u?e72XUUfnleWp#XnHtCf1pk(g7zklcY zKrM=`b6@`In8$Glo$M9v6ofRa*2OagaP^&g&jU)THpzDFZl^n|-iihK) zstE6x@K6md2kU-Djt_F&S5uFHr>TJ0!IxfU>xj$X#Yn`%T>H(wDEE)$wDW@Ief&)3 zO(gizh1wecl;k~nM&A{6^l16P_R2B+9bOYI@*e7){POR5Zm%~>#LNm?A75NJ$nz+5 zh<{>5nMPgLVi-@B~u%eUP}S8`3E;j6=(?@Bs7i8_n;)i*evBY4>#GKZl*;LDr@ z2>G#%!jJg?@6nyDdrodqJeP`NTwlAv?cCNCWxd(-l{a?qBi~gtMKwd@qo3+))7kvn z4}7Uk^_`UaR!>*gX7kJQT&xW^pe!@nT&&HjVefcxOkNCW?zbp^DzkY4X&7G2b_*wFOfR6YOr9tsm zQmuj}n;aV0@$-h>uR%#Ag})T&(%(P8qMS L^Fh7m3KIVdS{WL( diff --git a/tests/ctre_sim/CANCoder vers. H - 04 - 0 - ext.dat b/tests/ctre_sim/CANCoder vers. H - 04 - 0 - ext.dat deleted file mode 100644 index d72e4e4c1a35362bc8de5b20025f30b658c209c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2048 zcmcIkO=wd=5FV3ftr|5HrBxK42V22QDX8^e^I9v3w?f61nq%-5i1c6)!6HSY2uARv z;7to!v`Ez8#U~WSlM$5EOH+StqV#02NbAndelh!K^kCdWc4y|B@0*?3Jfi=;0GdA5rhpx>b#<=P~sxMHJg+va=uTM{1Q0DaaY`l+z^!RJTBMx9kAqX!%HG|_tP%9%j!Yf0CGc!V4)-kI!5 zPN*WhQ=&rwUIy#?jExR4Zo$-J=xHV-e&~&Fux;S7IG7!HxP$-MSCziWybfN`x=&w9 zzlnrjZlUG|0=4rTJ!2n%P6+D~Q=mwmsccI>G&z zZ{Mc1|emO=R$e;FI9H*qSVrJjxt@+f>gEMr$Yjn`Bpw7hy z(l6-X-F5Gp)BS@u{O+R6%byi}_>0E>x-$6b_RSeLe^&Al=bhgJY~bsDfFS&rU5$dA z15Rl0@XtGXz6PI3i~d4kxBmZwMn1zt=Tn0BRDkPBo)-MA;R}V$%7^(gH*4^l*2{b_ IFO>xU3q)-h1poj5 diff --git a/tests/ctre_sim/Talon FX vers. C - 01 - 0 - ext.dat b/tests/ctre_sim/Talon FX vers. C - 01 - 0 - ext.dat deleted file mode 100644 index 5ba1709c36c525a678b0f81cb950f64eb4870d81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2048 zcmdT^T}YE*6h3WcR$?=VSs1J+8xCT1wJvH~GulmH42mddhJ-i4F1iScwhJ#LBfXFa zccBGAjz&>;b&-K&l;Daep|Br?tcysr9|EoKyyraY+XwSPA?Ri7yyx#Z=REKGy{~9u zRjj@N=?bo5u6 zD6XxPgG{Oaw__b{?|RSq7gR2OqJ=ZRc-@mBE2JabW9m7h%k`am)@|a$!1T3`%sbI>!^6E{;nTV?MrV&X z7vAV%-t2zXz#s29KEfMo?b}~rT>K|>jF~Xs$@M$m3ZB{>qEPeQoa2jtIL6kL>NmIT zZMEk&ua*8^KhMu`M#0}6V_xwVMbAk;?-VClEqJLJ;o-~z`1byhA8(NQ;2n6i=LgP) zP7$@u&6@s$id(lUX1+(i&h=I8sE>T^m-|LO=HZ#x&THJdBk%(s*9LP-=;QN^s=xRS%*uK7 z_Xt^nlcyygc`W%Hp(7qTORfjKpm_H`jW&LMD5wWcB*U^JdYax*a(^@9Im1Up z19qpRe&+HOW4RTO`x5#l{U<6enfD9vnnv;r6OCjge{0v1DgJiv_PlJETD`p%_vD7} UqNz9fBQbG3JLG$`x!&;g2V8$2a{vGU diff --git a/tests/ctre_sim/Talon FX vers. C - 010 - 0 - ext.dat b/tests/ctre_sim/Talon FX vers. C - 010 - 0 - ext.dat deleted file mode 100644 index 1b3ac346e23ea7b51f14d73810cd09ed2033b645..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2048 zcmdT^O-NKx6h6*RsTipgCQ(gkjuFB1voJ_!DjTPr5+qU3K+@WUyQHRYArUl0s9?ct zg3yMn2qJ_Y@v4mw1`YizGI9|F?WAd}H@)-sdh=>rXqyf?_nvdl`Mz_%duCokb8buB z-VP9}Uo_hXXEz^EA2REl?Z4V22YR9aDf@rrmV>7My8mae+p4Zuz78hrvnp3mpUh@E zH~9cEkCzRgY zAB9#bsr7SZ_xwKL~14?MW0kK>AG)JPr{+GhH=zhQQrPtDgrm2PDH zp5Jw;iT2aP`}hUx3Gf@A-o;giy4e#&x@lPTLm%^FxUua>SAdT21LKa#{mwS-`M`M2 zNy#SDauZOGEAmTrJ6!7D2_Ncn*T1@VjppIa^a7xa$y^=PR|@LULGEWta3al&XB1e6 z#1iyb@P_t;c?G9<*NXgX|bb z`(kUT=ZY_~LV9C8^K$ARe&oc^VZ>2A6kk_gaMc8wl$TvTTMtX#$Ne672gG;ts9s*4 zk)N!W64jo5Pq=McCr91yTP+FQi~L?8;n#flq4Ug%^8;M3b+{s)`mX%BVidy4KV^h; z+nT3IQupsGW)OSqM+WVP5H8Mt#yE|oGq)&Y>%`eh-%l;i`GcaZzzb{u diff --git a/tests/ctre_sim/Talon FX vers. C - 011 - 0 - ext.dat b/tests/ctre_sim/Talon FX vers. C - 011 - 0 - ext.dat deleted file mode 100644 index 30078194c1a62bb1f6023f572b66a8c0b461ee38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2048 zcmdT^OK4M35FMKo`V%TB)`bwYHZ4+#;vz0=9#YeQn}VQ%F1jeLE4b^zAc8>zi)a<9 zkd0uQMq5FUBA7+gO+oxr1Q(6ig&?@Kwl?w3=Y*H16=^~665h<*nK@_fx$k9;CeG8p zUmj690oo04)?nXK?!TV@8SN`KtwVq!9Vj=fqkkZu@7-QUl#TVCT5?LJ><(6g9I|{R zuufdO`jPuDn_a_I{#DD@t)YdutIQ;>3tzBlwYeu=jYxfhI;EvGq@Dc_kIVUkIR2Q= zRoIg9SSRo_x*F!V(p4oSW+EQf52Cr6bSvP4&{eFz)O~IpU#)v_t$>^rp#x! zZ3iDGIbPgtytWU1^m~qm-vjjHJS>~MAI^Sp0rF%xCM%V4Gu1j*`b*q8u6gJId{}Pb zKDP>$w$1AO=J~n&NO*8R{`>G;J>&Dd;DKI2p3xQ63lx#~yx_)nT*87SW zKkDfR-e)abIH&#SW6Sd(_SKgv35ps#rAKdx`(TgWZ)X4(b+8fV6#K&Uvt!CPHTR~G z{{apSX&l7M7~bCQNjV?xu_E6VQ7rjE<^H F-cQU?4;BCb diff --git a/tests/ctre_sim/Talon FX vers. C - 02 - 0 - ext.dat b/tests/ctre_sim/Talon FX vers. C - 02 - 0 - ext.dat deleted file mode 100644 index 7db697aa904c85913c7e371eee904eb0e769cc3e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2048 zcmdT@O-Phc6umk2%U}w{s3{a#4h+T6YFgxcIfk<=h@x6Ffk>NRgcd>2xNso}^$`(~ zi=-ehl75y!I8ociBV8y2J%;bS`*-fS=e_wr)0KUw1)+P^2He&FT9YJ+DL$M%B_K4DrXF5d?HukVEq;zua5o0uTozJX0(P`1)>4fTOUX0kRyWET9 z=!bPf9B$~xHs^bMFzZlvt%UfaeZ)>8YpgFY(Hr4>}gr2U4P|#qG3wN){&*R=n(Y)#1W2_(A@tPw&?L&>eUUmqsrp&JmS% zwcciaaf{oyKPCUisGV!p`q3Ztp5e>9QIC1}S+JkilrazoKAw#~ck(FmIM=n~CsY^c z0etMHB*S%Pc^FSZy<@Py~Q@zl_e_a;b#Exds4}Lp3 z(Y)T*$Sv)U{72T0{PKCNM;-6X2X-L8R7p}h>iTcol;gvg-fz*tMIQF;=J33`cJ1V_ z_G`L#cZUCK2eN9rc!?j%fA5}cGGE5NlZyPe%)8Ca%lyD=ws?hc)uq&??<)W7ljMEr L(0yiSi{SkMnTsBl diff --git a/tests/ctre_sim/Talon FX vers. C - 03 - 0 - ext.dat b/tests/ctre_sim/Talon FX vers. C - 03 - 0 - ext.dat deleted file mode 100644 index 0894fca3f4693d9b54bc678a9e2c02e107c9a9ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2048 zcmdT@O-NKx6h1jtCPP1v%v1^%mIIPZttP1EfSj0!%-I+IYiV|s#&pu+8^lSf8GBJ+A~+VYWV^TQ{!B41^85de{)S4Q8wCq`gbQ$ z(zdb~W!lDzzHzeq#wW&Kv+MFtv^4TtC{T!*l%Du4sprpLtnY`fUCEDAL?9ajiahe{ zgq+{cW`)2M>vF=1?M2F`uRZsI`#Ae;) zUL;2+)(vsEpv@9@Tq!!6|!;z{d>n{d8!TlP*UpY{8e(e=MXx3>)%7~3%4epKJo z=Ec8xdQ;xRb$9R&BSs_L3DMQ^HramimM0ZdzVvt1;mQ*H-u{74?$Y|u9ekUv_I1QA z5aoB)+~fYDmN&dFA^&5E8hofPkz1_r+VPJZr_pZ;|9IoF&{7Tu-2N*U`zSx zk&M=B|GfVT|7!=*YWw+OKehkH-P`1R**bkEMftbPyB#QquHfsid=<7}zI9gO;rFW3 RtJ!0d4>Ciw!#k>l?=OQeA6EbX diff --git a/tests/ctre_sim/Talon FX vers. C - 04 - 0 - ext.dat b/tests/ctre_sim/Talon FX vers. C - 04 - 0 - ext.dat deleted file mode 100644 index 5ecc444cf8fcba7abef3587f191610f3242f3d7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2048 zcmdT@OK4M35FMNNE5Q#asnS9ewSj^}aS<1qXH#jGilX=dBNTBXL~tPrHj6Hb1$~H! zm_>`wMT^DOr5hhK)=j~-2)Ym(vET=k7QYBK-kG^4ygb@2S`fTE?!7Z}X6D>;?;EF& zwdwk<6#c`oEjoIDC|~KhY6-n3=)-@_|0(U7tzEWw0Y+%&Y-9=f*@1zUh8m)tM9Zn) z?L-+%WxkR*8!rdO@s68sIsdv{7k{FKGrvSbQ%M8qOx>1#LG*mQ`^R0urzkEd>q44& z=+QAbf3S|<=5u))GY;!yJ{eE;YyY;8`ccn|s12T#I<_Bd@QKh0ak)0&ets!@5I;=O zl^jBx_sqk&sC_6kGKivJGW`~q}H?kz%sVxhv@dANdvFeR@)C6 zo7?>P6GOM;J=}1I|8T}wydy2T+Pck_Ps!HFMzmh;tLkuhf%<;_$j|K1{?Hxu)?e$p zn!G?%+TPI3{1Ucq-QKkPk8yjhY3oOS{{( zoj9SoKo8W%YErVCXNFg<+n~ES=JSQFs{8TZhhy+upLw7U^a}Pl+pc<{g;)F~b(32* zi+=EjvH7O=)pJk#13zf}fK6S}eB|-U_W|37FO^f&h`d2BhV7Nt@{(ZAy)t^ZHM~6k zreAnF7Pc>^{quM3isxaIzL(^8L#32$1 diff --git a/tests/ctre_sim/Talon FX vers. C - 05 - 0 - ext.dat b/tests/ctre_sim/Talon FX vers. C - 05 - 0 - ext.dat deleted file mode 100644 index 09f966de33ca3450083453885641e575920ac420..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2048 zcmdT@J7`m36h0=lRwy+JQmrj0iUy(*o#GIa*os+%l!^}&j8ddaA%jCfF&&B)9qb?? zcCfm&H7JfQb`Vq4Ar*&+QY#d+2%@w;5ZZdrpSOs|9@XlXt0L+hV+<6rKzHMSZqV zXlV)%4Mbaxe$Nx7t!X95oW8?L`-dNH&ANzRA*;AG4x>`h#eetwKfa}SO6 zNq&ODQW6SkW#-;N+24=jwt26S)#)Vjeycn@LBKN`v6XwkwXAAuCne&r;aAfbkr4r&l?IUi&ey7&%e64uq_o-6d7rDph z5e<}AcXeKUcd+Np#xRbLoCRzq&xaAdG5!3AG|}&O>Z200S|pnt1WB5E7qCp}e zi-vYq($BI@Lq)b|VPP~oClEp+F|>k6r+d!1-!O9-LyQ(39`D}s_nmXTd+&SN^`riC zokvDG{A3HS|5{#k-``Kv8$+E{*p#kbsajqeqsV{V{|JTWtCy9ZZ86r@6q*nIMSfy< zxUHdrC>?3*{Mkbkw?!9%^sPVd$nn0bA36WBT^G~)QeviR0uxb_*dMzl^<0dF`o8xz zCGjx|NlGxFnTMYollfhoVx8y8Y>0czllerR?bG^Q0ks1!Q>8lkEa2FB(9zFoS|g^E zb)>$0kbdAlLNzPd1wZe(5AVFzAqV$mh1wB6ZTsOo7Wn&BE&LG=gZn0jzTW-Byc3-g z9-fXUpXSDh&b-UHNR0lNH~3)&f2?!7#~ULD+bhMzKdmEX!hB~o?jBb>Yj>8>>hHqa zSXdp|wWa!l<^x^D`R^VN$bA^t^J0!OMniqA!mGtSWc$fkoJ5u4`7_Ex@(=jM{UblV zP3wbq;H|qfbTQgZlxu3Z!~I1pZtdPyd5y;Scr|*v#sArEh9|vhk0s9bpp}G#`1qazD_E;&b^JH6yS0`VHAW4D0!3 z9bCj=Z8V$b?Ul>l3~Iew+tZW$)>?ekUA*Ww?SJQvO)_7?-jlq%Ekpj%8JQn=w=G_y Xue{{8>b(k{o0GWgl-eh^)C=BkDa9Xr diff --git a/tests/ctre_sim/Talon FX vers. C - 07 - 0 - ext.dat b/tests/ctre_sim/Talon FX vers. C - 07 - 0 - ext.dat deleted file mode 100644 index 51bbdf13c5cc8a2e8954a7cb7732388b14c00bbd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2048 zcmdT@O-NKx6h1jdWkV$tnkh^{&VXc7o2G@$D=lYPWJa}U0*NSu7gP)c>B5E7qCp~} zStLOVE9qz1rU7l*1X%>RD4a+LlElaoqMY72=YI0$GKLf_x;);!=kGh;{qDVQDLhj< zQR9#|+T2tV&;NSlI`8Zx>W-t&GAxQ`r`RlQy`ji|&Ho8)nXOnv$mEtLEGv`Eb~8a^UmL53D=U zQPJViQ`OVEF=DgsaxRjiKh_O#xS=20obT|$8@pS}CB#4NBW}X}j<4N1rg+A0O(QG5 ziEghNG%&id*uERy)#0yy`JhkkL*KTcpIk8#>1h^S4elPpCvR|)LB(^ws1B*$;QRTb zK2fjzp*!#@FASWIbrR(_*4ngIqaOR=Yr%dVW1fLH z@NsRD(}&xT$GNs0J*2uo58z|w60Y+`wotuVS0(-@GM9?Z$A2DV+1`)B)iiTVEsk!7q=7jcGlv{_ENw`S*<<`QvA_9(6qPdBFDN=L>NPqpthvHCf(k z(DNO&aFK^O3H-F@}*5s;fF7T3eSj!tn=VC}vU%6HjtyRZ#rTWXE=T*H)O_3+mu}C!ADgylqKPVvqkh)vK>_kZ2w01Hg#G{I=;xbndG16f zWeyLX=se9ABRtc{~T@Q%^Tx`D@e_^aVKuW92T4}N@( zg}LKBsN-6{U;Lzb%me(e2J)Kf7)d#|VZAZVp?O#Qw5wK}zU-xn`|;j~V=9=Rb)XOC zSAu-q*-=?T`9N&iY>U}EidL_Dn$>=#H^cAvU+YY%@8=88tN!*Ko8^4CN7rcMl}H|u e`}6Zbcl^RPnNO%j?X&XX(yi=7OMYvU@cjf-)hsUn diff --git a/tests/ctre_sim/Talon FX vers. C - 09 - 0 - ext.dat b/tests/ctre_sim/Talon FX vers. C - 09 - 0 - ext.dat deleted file mode 100644 index 70a02da771f9f67eb72410a5457893c35e9fc5e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2048 zcmdT^K}eKQ5FU5kQZY2z|kO*2L)UaSL zL1;@F1Q9|%@mCk243z4U(H;b$n`CSK+nYBtfB*j5A4XjocK5xRH{Un&zBf7tb%%FU zA8G@(npLwkF}wY!_>iu(xBqGrALxz%B-Pi$(p4S@#o>9V{jd9f4hO7?lHz-cDdl_}HDC(p>+Mc#i{XRd%h0mxYU;4CpxSsgZ z&*hR_0AndWSlICH;$C$LIq!!0_0DtLV;@G<%mvH?7q97~xbPX3oQFVVrjPm?BG>+v zd!NQQFfxUR3G6F#%<&K zo!@fs1M%4>1)Fr^9Y8&<@qe;=p+f(D=vbc<|7Pljo`<*7%YZV*=c_foj9E`6sGmvZ z3GXI8BS$*Ke#1{X5s~0yjZ|NB7rqYb_SuXDFgo&H*9Yd^eB^Nl_Per&>vCM`3m*H$ zc@VtZ2diToZAob;=fcmjLTYOb)uq%TKioTb9C<_!;g{7HST~NwaL;AYdQ|W}&iBAO zAiuMY=;f|6{GIfYLdgcwt!3xLi1U4Ae!Euby@Fg{^5L7zGcjcc2roEXah}9?L-Usb>zW5o)_*@-b?cH`fm&1^`<$^ jGc!i`?73Uz6^fyG%GRTx-&bEweY!hl24C#TXuW;_n(Gh1 diff --git a/tests/logs/FRC_20240519_053213.wpilog b/tests/logs/FRC_20240519_053213.wpilog deleted file mode 100644 index accbf5622350832b877a837fe78e817e88398b7d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18698 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 diff --git a/tests/logs/FRC_20240519_063231.wpilog b/tests/logs/FRC_20240519_063231.wpilog deleted file mode 100644 index e7755c8fd4532c7888a8e9837f3b52933ec8b5b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17776 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 T-Cy~S-9P!>{PNYm7mxo1yvyM2 diff --git a/tests/logs/FRC_20240519_063410.wpilog b/tests/logs/FRC_20240519_063410.wpilog deleted file mode 100644 index fa42571000fca0a6d15ea912c1274261ac13e7ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18696 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 YF3Hgs_BB2o%}A0iJ=b`y`e8x-ALN!GZ2$lO diff --git a/tests/logs/FRC_20240617_084719.wpilog b/tests/logs/FRC_20240617_084719.wpilog deleted file mode 100644 index 682cef554ed7475b35d376bc43dcca997db0b490..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18667 zcmeHOeRLGpb-#=C^|4boCr!v{)5N89ow`1$lb%+mY16b#b8y`zIoNUg zyKnX_v#ZrIALYN!Idf+2?#%tYcfa0!_r2NQ*V)y(iy|bB6(sJWATpX|sbiW|k9*5D z_3W7Q$S$HexVsu>&tPk8XZJv7cGQTiwM4m z?H(ZbW67+ji>MBlrDZI;RXdUD$!A71lmFJU_AM=5L{Y~Qmq#}dw`dtow=DX#Tw0w7 zz`Wkgd^b@87?;aJG<*;$^wsPJH|IVgCa)`NcBj>^CEL?!UCkymh8{7Dw5Ddgh$R|f zbL=5%tiX7{R&CwL1`tSNR2Un0;^-xsi^~Uax}^=v+-_uT(@5`7ZPk}l=0-^YH|MyU z=qlXZfRovG=|{BvdNyf{$JSfuK;DXV?N>Uo>PT8k`jpO9!f9cN^T3?XoDG6$vk9Sxm)`VqinL#~s$trGk*hxQT*>o9W z-D(!0!UVHX!_25QfNZ=Kx8r#Wj!p-O7U0EII9Uh-8P&9Rs8(vkP|aj)r>>=wvGoZ@ z+-VktPf08gk{Bdv0>bjDDE`A#6T%d?aAT6_E~15(gXlL#44XY6Y2?wBp@Uv5eIa}M zEC+gr{-JjqbF23*>pPlVUFYQUSo?bdkfiHaa}#NWVLyJSy9gdOh6CM9dwn$@bP zncP|>fq~l8lnvLr|0(>qx%hVr$ME8dR!&n7Yi9A^O$z>PsmQkY%*Gqt&&&iUKDg;a z?gw*5QqO1BDn&>%`or!AihmSXZYnZr`3RodEL&BHQSs3YEAi-#j-BoMx(1bXN?%t; z`#^^>(9zYgeNbsv`a9aYl6VDOKHR4Ey6q8>Sp2`e745Uc+dSGE(NQOTT3^sl!pP)c ze_7j#B~q$o=~gUbB=c!4&KZwp#VpOv8OV(-c35aEpRij8#x?VZhM@(|ac1Xn+@x_L zjtc9%VrMkf%9~p9{{TASnB**j$(@>-#H2~->)a7)u>7DHEI&cSA%~+%1s5p6@;^|1 zXbJV1#;A@I6s;|!y=fjVk?(NAp6<($?APwgYnJVE^3LAQ!}lhf>shTco79dL(CYA-=Qik zc=<>>;@ynf8Eq*tLCR!0Ws=Zx&Jb}#z0D(DcwwVw8v(|N%gp{%lZ@tA151=8<4P!b zRv6DX<))ZOCu51cX(HKll1uhZXAZzBzFY;GO^(&jf(xIQ2NRI-q-G^dJ=kQuWudG1 z$oPDq!)yi>ve*h8cG|$BtnW&}=FI|p9vZCgDoO8<8g z-GW~@Ln)Jzh2n~>nX!Ssj*cDiuFmexL4PswmMA^>1RsC2O;l)Z1qO$_S#dghdOCY{ z#RCK0>INKkJVMq^T(%}V7TV0%p zX_V;WxKx-=m%xO#l#eeHt5}RV^FU{};#W>0%Y1zQEW1Gy>rU8lBY#V@A;4G7s ztbinq_-H;k=67YIP2_<4iQ2(hsmk8UAP%Q|CSUDxa>u?Ur=Bjk$>v*HHW_!SIF?U{ zJH!kNv)k=}s4#vMAw&fzo;DJPeIlTahXd)&4qSNjDAPe9z>0t(3R5u*;5v#x@zM0e zcuLdKaa6!GpL3KQ(f}CTAnL${BfMvDJ)3~ht2RQOnjK5~tQT}d>Ah#({_F0MAHx3b zA=(M(RbJptfceDQ>Fz3=Y!`53y6!R-$75Y$*0YDO8d-49ATr)1r%!L7lPRJ*0n907 znT%%x7K#sod#CL11>mYgoxrS+lFY!(V3vdd%)c>p%3~;oO7G#4Bw0Y-n$_YzV^W zM~md>;;&VKvZMZeB0HK3R6UFASWWAe#*`D)c;3eA=USH6GvX%iIzZ^nj_Sg3a(d!$ zJfCaA6QXc{AtuS0wP6!Y5DnmW9*@f;e7W_}@G53tniOk#BAN$lKzL;jR#P?vv=7Z} z#~G%5fz-b5im4r%N1j^Mv1TrLhu1h`(s3drv6W1&7)xfw4zKL})szjfptvC>c4f-; z+O$A=zWa*l`6ST+bcl1MvJMs9d#0?5+YB~^*EploLt@QH48|c^5nlJ7sHS^}3JVz` zcMjdiKvpnx#jF6sC=xC)EuF1vmA0FN*FK}t39;!<%!vY^hu8YSYFdYA?nN6bWEe#U zsUjMuae=gb?-kSbq$o~_X+xR3J#H=vulG3X{WQ@qE}Wr;YDahr7_MdklVVm^DMb1c zR|s2Bub3@ZVg@Nnh-Eq`4rs*PYSm&^AG{Ia6+c={@emYh0#!$% z%L^)mpO0NJ6ZoVkiB(EoJnRw;ZviQ`0AzWn2Ud#r-rL~JPqFedj#c7-)p%W&NEWsc zJ%~>q&?qi8m6@gYMqQd@2W-(H*`md0(J7+CXbqRzg13lwMTS~>K0Hr+x`jp*4pbcn>`!-Q*LHS7RgQ(12&&IJf>9Z(rxFJxW&H-XkNe=?HJtrBn z<)WB+ADAw!z&KE=?~}~gQDa0V7_;05oLvO13T|u#1?@yi;ctknI{YcN&ESgTCe*)h zS&Xyv6|t;Q{xnj2Oz%Z`yZE&Dm`Abkyp)Sgj-;V%_qdM0>m&wpj=jImq8H%>JYmt;-e@HTfViT9Cw3Z6sQCy z*JV|k2OY6onsWBE`|Q~#-NHjU201zo<5H3YgZTysx5|kqORaDybbu+;c8ab!3zBJI zOvM1=Yf(!%Sqdf;c0a(@;AHD|gQa!;7C6RchsEB^NKl2{Uyz~7J(~m&;$StfBt8~4 zCW4|(7SP5R?ExTFSWYY0qHDDmAp%Ri&YCua>eEUdC}8T0i43mN0&@k-;tKu|4Lb*P zd%~YCA1u}7VFpLCR%th26>yG@j@kO`^eOIiL?O{>%%(hc+9l-xxsUQG?sWev%OCpp zz4Oi~l;KVzkuNT8xeT~Mr%iR-t>z#Nc&JqB8aLq6XaMqoa-*Kv05z9O>ljn9IWd

zA$I6KH&!bT7l4I+&j9omkHDse>TdCGr*wSb|ot`Kt*>75>i&-RPl%MbLtReWO0Ys1ap;^o7Qqe^A$7bItYjq|A*@-rcJJo)7%j_v5qQjtn~g zQC-_R&qdbqAI|N%OSe3x6nit_?fhu&u9njq;|>$R-F$NXOCv?z5>@^bNdr{bQ0^{kf&X*=Hm*{p^z6XTL0|wvmIk=D#ATb3gsfzis-Oq=w)6 zQOkSZ5Y)}{qvuwvkNn<)-;`wAOIBp;=~pE=b@7$Rh5!0XNmBd!k^AiLNb=G5w$J(V zMQ=)y4xO2^`=z%eIr;u;bJm{zdr40H&Z3&%|BHW=WZT&THDCPIA4>Avil=HeJ^pW! zob3DOn&!@*NOJ1pn%Wn?`?e&NUp8u6HvLqRQ!8Jt{lbcil5DGgx3+)$7m^&l;f}iV z9g$jAC;CgZ57((Rbw%f6=h+%{7u7Ub{U?Usxwe zYC01=KeR!TlV5r*`rkKhmL%P_xbe4#Z1&>9-0<~nf`qNTern0q zH@YO%w`?eKV6UVu9RAX&-n%5V@aI3?|M)$Ef}9@R^K|5%Cx<1uaPNOaUinc{lDWq> z&UyD_N|GvCn?=&1-|8+@D)wV`YjQoithc{0~kDvOM rBx%{7MPE2~UXoK6uWB6L`?@42C;A(QzWb&mr#}BgQ=E{T^y diff --git a/tests/logs/FRC_20240617_084856.wpilog b/tests/logs/FRC_20240617_084856.wpilog deleted file mode 100644 index d6e7cdb39cc4095a799454ccce708b2243821784..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18642 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 diff --git a/tests/logs/FRC_20240617_085013.wpilog b/tests/logs/FRC_20240617_085013.wpilog deleted file mode 100644 index a0789da71d199bbb86bf60fe388542ae1d17b799..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18627 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 DkQdD? diff --git a/tests/logs/FRC_20240618_075839.wpilog b/tests/logs/FRC_20240618_075839.wpilog deleted file mode 100644 index 3b7db55e4f8197d3d641f758abbba1b3d3d11a68..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18725 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 diff --git a/tests/logs/FRC_20240622_005426.wpilog b/tests/logs/FRC_20240622_005426.wpilog deleted file mode 100644 index bd73723b5ff971eecf9787a2afbaebe983a46efa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18656 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 M&oy>-yer8615P>m9RL6T diff --git a/tests/logs/FRC_20240622_010544.wpilog b/tests/logs/FRC_20240622_010544.wpilog deleted file mode 100644 index 1c9f08764bfa197bad46dd8ebbf23f108a140ed4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17939 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 G^8WzqjnX9m diff --git a/tests/logs/FRC_TBD_4993bfc6c3d9d8b3.wpilog b/tests/logs/FRC_TBD_4993bfc6c3d9d8b3.wpilog deleted file mode 100644 index 8e4c2dab4dd6f8dd8ca304d7a0a0ecb98e9a7c2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4515 zcmeHLTT|Oc6h2NNkkCSI~}7EZp&_KtG>Mn1&GE2h*s11!xLKbfzTImt&MX0 zK}@m}Cw$XH4*4Jn3hDrp z__;L(+2F<+Hbbu`6m2`c`EDhPDJIF{qtO5$iEiUe+hRuqERo8X6ZwX@ElhPI3&tjJ80=Z)o;L<6;ZNrTt{r51) zrRm7o5EI8Xz-9b=iZg9(^vpHs8ztR!Zg?)MT%HDoXz}<7U3@UY!=ko^!sAik9g|Sp z7RQ4U@ESkCGh`EeppEc4j(6-8-^OsGI40ZF<)FcROce^j`ciq^AR~jPx~3ay40L!6 zFpCEt;UpupJ+90;*TbIV$}Vp>!nMmKD>k=FrpRfD*~k(dfH~xF|4c6V)6^WMDU$H1 z4e%1+%6TkyWKSB31Y3rv%B$B|JpBqq`#T0|hx(y*lylG4&d;6Au1?0<0So}HAp^SM zQ!c3*8tF?EID%YGfL6Xhy48_XrvW9TPZp7M zy|z((QSY$FtW~d7+cnm%)oW`VR%JW2YMnK<*K3sdo6;9>b1@4!+{#9VL5pFFK}(q` zYtZJ;N4Mu-EY(D*kGhJxq}bc#gUDIk(NWIL5jGQd)(TN$@xQ+%{&^zWGWr|9pK<$C zI=UZAdI9>MZ*r6tH+>p=B!VeWCUQmKLO=&Msr! zgna-`R zd2b$CO7IKLZpIouclXD;`Mh<^#V!>Pe=5fCr;BGGeLq!f5@^-%uQ_kp>;G0D!ua zWEpfX Date: Tue, 22 Oct 2024 20:40:05 +1100 Subject: [PATCH 16/20] remove more junk files --- utilities/__pycache__/__init__.cpython-312.pyc | Bin 168 -> 0 bytes utilities/__pycache__/ctre.cpython-312.pyc | Bin 252 -> 0 bytes utilities/__pycache__/functions.cpython-312.pyc | Bin 3306 -> 0 bytes utilities/__pycache__/game.cpython-312.pyc | Bin 3905 -> 0 bytes utilities/__pycache__/position.cpython-312.pyc | Bin 4528 -> 0 bytes utilities/__pycache__/scalers.cpython-312.pyc | Bin 2523 -> 0 bytes 6 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 utilities/__pycache__/__init__.cpython-312.pyc delete mode 100644 utilities/__pycache__/ctre.cpython-312.pyc delete mode 100644 utilities/__pycache__/functions.cpython-312.pyc delete mode 100644 utilities/__pycache__/game.cpython-312.pyc delete mode 100644 utilities/__pycache__/position.cpython-312.pyc delete mode 100644 utilities/__pycache__/scalers.cpython-312.pyc diff --git a/utilities/__pycache__/__init__.cpython-312.pyc b/utilities/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 79428c858778d539bc480574eab99238d0653589..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 168 zcmX@j%ge<81d9tj(?IlN5P=Rpvj9b=GgLBYGWxA#C}INgK7-W!a(A|h2`x@7Dvn7k z&PXkaaY-%CF3B&5aV|u*uC&Da}c>D`Ewj%Lv59AjU^#Mn=XWW*`dy=l&}M diff --git a/utilities/__pycache__/ctre.cpython-312.pyc b/utilities/__pycache__/ctre.cpython-312.pyc deleted file mode 100644 index 4a60eebda86a74c81199ea7ff1199666243de69a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 252 zcmX@j%ge<81d9tj(`Ezd#~=<2FhUuh1%Qm{3@Hpz3@MCJj44b}OqI-7(25#E22yAnmplI+?}vbJi+lx4?~Yq=7F7OfgN22=;I5C>N23Y*=PxHd)7 zZa5hKoYE=~(nspg=)ZhZ0){aNAsRDOkv-oI3NClxRmP z+6QuG-n@B#v)|0TKXrG@475+~U!VUhz%c*BPP=urgxx=bu*n#V!6unmaR zW?nXWU}h-97)M|>2Xi=M-;#sz$ot}~3_EtrGNNBwM>2Y09VN%c`o6@=-H5SXbY|Hk zOXd&LMmA~AIGSUEQofl6$x5e24Nufk3rW+Hi0NcWN@sCmt4Y9l`0wU{Y%Irb9rRM0- zNH=VN_p%3p6qqlRp7n{fiI0rU#73f={dM{`&ZjF6SGL4Ye!8PvtqE6m!Hn^ExP`|j z)61Tauoe%zch_bu_<8n1b_r_t7__!sXJ+cP~LZ) zI;0v7!JB@GK#g%E2+R``xlG!L1<3&P$WbK6kf8TG-XsJ+@q#D$%X>l4%%##~(Z<>E zd1>>%argdabE5`11qKKSdmBiBX$G0D-qNYH@seF0*;uM8FO`=n+Jjv6a`pbBvHB|` zHF>l!`9uz{53LQA^qPFUFxd#mMeXM+jh_BuH_Ef+(`$2o37l+1`_`nVeMige##DJ` zW4ba}(H@?yUVb=SJMvmF*yueDTb!@R_1>ZC&3f-^TgSFfeRg6yUmv;t$M4riZq%Z0 z6{Us}F5X`oD@}pzbv%w;8F{c&mEbrbJdQF_6GkW;pF`YU$ovD`2#90u!u4KkclW|) zf8=pXgc+R(ZfOx4tHL3xL3w$x{ST{&F8hCISsY1McN{*eX5PcPqndhXbv^fblpsv5D}2gRU>ViDMvL|bkj6C zVv;UQV=@+^HH6?@J<-m99f3T>&?usjN={-IeM1mjv91FnR)WMix3mKBiah6q{2Yp^ zJu&A=DRY@xQ4Utf>82h}(vFROrh(leetbte;@iJB83w~w;BWr{2*h|V6OOLmUc0@1 zXYI}hb7lME+=E=b`&?nF(H%Kh9~s!}+UWXgM6E~Eoyh6Rtxw|*TgP14Zs>PfXO=+dER+X5 zS6l{a2Vl8{MK;Gd_&}fy5WZJLS9zCjXM9>4I9fqa$J6SC^@8eXz8CTn6fl$RXMz1( zs(;s1mn|m&1pwbK*_7p|x<&M)*?}^Sg3Tu<;5<;ZF^~J$>O+O#m+=dzeHn-sKx{w> zu+asG2OkVUTF^1iUjqFV_}gy*DKO8147^JY%HdDK(b8aPX(#-0;aWrKEzOjp8@KAp ziLzc-PF1c}XSSk`Zq)}bZ|U{H@tQJT6UONWiLnbm>HFQazvn;tE}))Pt={E~g>SKo z_pFo&f~DIuD!fR0V8Ki;nhwd)i1EbvWLk6R1B$*uJkiN!AUv@~Q4rHxJYwj6^nzan zU-vQo9Wn++STb#VV>Ee|W&g$~pEH*}XI^be9Q*C^l_mqM^7byWrp&V6EM}VwFdP9^ z6)D>~vx~iEu$vuigu=ya$t=3{(8(r`inHgdZ){zuPS?+l`-*GRKEL@6nZ>M diff --git a/utilities/__pycache__/game.cpython-312.pyc b/utilities/__pycache__/game.cpython-312.pyc deleted file mode 100644 index fcb20619c3e48cbfe25aedec5bcfefb20e81a8d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3905 zcmb7GZ%kX)6~E7ZHV+=g7@L3PkAaXB;*kcjLdGcJj~zfEK(Mn_Pe|4a@7dTG+r54? zCF>+ARoeQgM5_eRI)y498k9+Cq)OesOxwP$ll)|5giA*|>=KDcOpFNmo)H** zY!Xa*Zx+nZn_}#SMX+pG1?xtYP_@Ac+(xxf%@7ljO;MMzaIptzQ*mT)(H4U%_K%o6 zFW6)z+Fq0!oMdhVRN6*!pcsG zE$qXkk1d69qhuADWLNY;-oBK|jg_Q#aMc#6N@$fh;U%eBXal<+mCnoak4{AJy=u7) zqD&r{^CEqP4*2Hxn*|vcI;9%HE%CA?WRhy%WrZ%uCRYPr2Yk0=m#cuU2fhdRGr&85 z?*$tU_y*w5N>2G4@GjtA1|H`&0^cV!$sCNi5GysqxPOc3Z#ly4F7#V8>rx^m4@vp{ zlBCrvClpbMB;p{m1*jNL#VQRiN&WRlnExY8#u0jd#3HdEL6{y@AproBqiQ4w>LVUW zEfO1&IwW=^^*|_UDayjD{}!gkxvq)u_{2B={QL_t5&rAv*m76G$*O;SFf;P^E8!b+ zzu7+b=P#~kOmg)Ei7=HA{4Vb2_)Q?YL@DT$lN=H9Hi_asPcIQf#H)>vXjiy7byzMr93fhlyR>)Yw+(UqGi znWk36)S66JymD$?NhDXMshnDs<5Hq)=;F{1SCU(+hG1n=iNqpGL{6=Q#SQsFa!YfR zd@`wnfOf&^ui$4qK(@(K-tm;{+IM{1@lnSEcZM5$%606C_oMfszm8=%&#}c^Yt0d} z#d-|pL}Qe)JYaUluWoN9LfDiCqwtSixi6ajUr8MWsp^d(S1at!^~}IjhM!Ke)Bhi1jFnzBOTd)ISSiF9 zfKwr&&##)(Ub7TSi}oTpi{u=VJ|HFT(l!(#nL-6#@0AN6!w;s}LERC}N@Zn}##h0( z&~V$jL%#$D94aU(f#yZW@^{Rva9mV^%R2aJ)C}Byx07%z-qLJd8hKNu{`}Ra@nKn+ zjKv~id{x%C0>`c|%hCbSea#;o)<`NyWr@B9Ud_Nig`mMWIkLQ4<=t7{qw<~%Kk#W& zcF?B|`m%!y>fl0l(67Re_orEZ9s-4^08@xq2nMAPFwO?*DuUrf5%UwJ5S16(<;#K9 z{m|-{ecqsd$v1h;w;Wtr^!q4gUvo^&-}IHs$3R{ZjaCR-Fq{x$!BkQf*JT=ndj&3? zM4V27 z5xNYkRf^DyPS&>xmWqJ^lfE_0t|ZDHJ8<9XxYzI7e6F1(_jOQ7=#Ek!Y+xDv!sjX` zzBj|4%ksl2Kb+w&|L(F{Ec5>J^dcB(R%I(0iHEg%nz)rvl3PJBNh2{u4AT)**8?Q+ zP`VJ76C1KZxAb=eWkIJO@%iG_Z@A`ILX;+Pc0dfzi(83J%M?*S%2f`7rTBHYL*ZLQPGcb{j}5A zTZu$WF9aPKdWLB^(7)xzHWJciOdh8z;2vTm^$yUSnPHeO3I8RreMOpqeq*vSrvDNk zxq9OKak`-=+c2s&j2^PCEZd{9Jy~{8We1PVCZ}oJp5sWh{r$T4>e9{gDtCR`^33Jl zxw?Dp?zKa<<`;|aEbiRgnc4fv&Z5fp9X?CZH^RTfsO&SgxJAgiOU(CA4 zRQFiMJ^rVTL$+y;*~1M^F{ZDHsS7^U4*PV!lIM@%j^&2^f{kg|Bv45XU6{kBitIE diff --git a/utilities/__pycache__/position.cpython-312.pyc b/utilities/__pycache__/position.cpython-312.pyc deleted file mode 100644 index 0ba32e8c85b83440d648d46bda03517fc1df4982..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4528 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 IKqwpYKUWJPLI3~& diff --git a/utilities/__pycache__/scalers.cpython-312.pyc b/utilities/__pycache__/scalers.cpython-312.pyc deleted file mode 100644 index 4692c765ff4fbd53cc2c3fef0426d1eff7b7b301..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2523 zcmZWqO>7fK6rS~eymp)f2q_SC0z`_d5G902DEw3@kcvWrRDx82t7!2~;!QTYW_C@8 zwW+KYRkW7|sZw(2!4f^B;*#FNt-T@j5|bXHEtQaZ;^xX6Do%ZGcGnJKqTNM zzVFTckxnNGv?uqj&ix%DNop9r2$SYwYV={`c1ZYQ zO*VfBFUCcxX~k0jLO!|3gZ@XO#!!Iy@w-5*b>8JHOr;~n7Z^!*973;eMaDSPlW zZfe?%-dFSzbKC3!XI8<~RX4_&UE)SQ|auYe^y~Z3)6ebI4QQb|j4A(u(8|8*_=a5DBc7b|B)Zzj_&NRSh{3>atA8O_B|l zjfrAWU!e+BnWC0WgHhXro;V5B40`9($l%DAL&+qCHdD|n$_%Rn=c9H(u|Y5j9h;hS z!q$vp$);9O$uqj76d}rNroapw_wpK#kqx_H<*wyMmK3|-Ch}%+#nR@DY>4B5IG)AA zU`pRkUK-EcvKY5=idA4dcbQp>wpq+wf|c{kP)&Mz`1F}vaU~x(awS{SHCtm=&dMt~ zOdTq&xa|s_bv8IDM=ptVu7Ob@^(0B9*V_J+dp9Ot$h|v}-kOj*a_`G{^3m8g<+ZCX z;=OyBj=fapkC)e{9#2)Xo40lkj@DA6+tT*cXX%%@^%Y4I{1^Ie=5e7rDA&>YD|-iX%XK{)}43Oq4afNKkJKsZ!BKcg%HT<>8@6+`tf z(f~&Q-JtA25g1_DnxfNuiQi{KJPu1{!@La?$ExJ8BxLnKY6sf~i36dCn*q#c_hsQ7 z;LTvv7>EjaC1=+9zCT;J@#ySJIrGDX?=Ebd{P{$cJ^841WN`Cd?a1)f%=W~uU(`Oh z_*-;WTqaLr;zR(NEALC6N2&y^dAn!8vrbxd)2a{$?mValCj>VJkwG8tN*M)aeh#Dp z%D{y!m@Ag8CI)l#e6xS4Y46w zFqf%e8mDy4U<#-3pp|qrD0twB#pqp@6&XC1gaq26s(>*F4evzJ1;WBEr1xl#pL zo?Wo`K^QoM5ywDO$eS*bI{MSa&Hk;P-J|2%*Pi!1yRj=@--%rJh#(6rW_5F!ao6vZ zibd$8%#sZ-`9ncZjOClP18ZP);cgn^AfO8U7jZS}M4T|z&}s~Mf|e7-cXBoE#GP0f za=7whdGq7{T#VBUx0#@FLS?Mwbzf7RkH|6|@=%ST;1z>={4FKz5MAM4UVfmIvG~ zB-`d8g%I#=6o*mtfNnu&iotEAf&J`z5K0;J`A+u|R> zcprS$IS}yPc9ZVD>bcsXq001L_wj13);&_Wv6t>zyHiWk>U1r2x^e}(v$gces#8mk zRwno4&dQX>gph8!p@R0#8-Tb9Y;pg9Z4+IAo~U<3Zkof-7N0eY)EJ-K7;lZ~#&pVs7K8@wj>?L_*-cCyku1VH=m<7`|!mu_@UHx*md zgI5_yb#VzItJs5>E7p6PIKO17C7oU5{Sb%0Nb5O>dRUUAzldCqC8STKjs7}8y?Mpc zTdX1a_3ki^j@1e3&8Vlh`WvGEZ>mk2lGa$ApstoYy$#XWe?Ha_y55tKy5NBIFz8pE z-SsHwdW>`(uE)_zkOMvSHnfsx$!MiWOm3vnIw?uV*I->xxD8NMSP#@z^bIO;(*FT8 C$aH`J From c0889947b6468cc192f0ff757400bf02a4a69df2 Mon Sep 17 00:00:00 2001 From: Beana1234 Date: Tue, 22 Oct 2024 20:45:25 +1100 Subject: [PATCH 17/20] clean up utils --- utilities/game.py | 29 +------------- utilities/position.py | 91 ------------------------------------------- 2 files changed, 2 insertions(+), 118 deletions(-) delete mode 100644 utilities/position.py diff --git a/utilities/game.py b/utilities/game.py index 016661c0..78737e61 100644 --- a/utilities/game.py +++ b/utilities/game.py @@ -11,6 +11,7 @@ Translation3d, ) +# TODO leaving as placeholder to keep utils apriltag_layout = robotpy_apriltag.loadAprilTagLayoutField( robotpy_apriltag.AprilTagField.k2024Crescendo ) @@ -21,28 +22,13 @@ typing.Callable[[TagId], Pose3d], apriltag_layout.getTagPose, ) - +# TODO leaving as placeholder to keep utils RED_SPEAKER_POSE = get_fiducial_pose(4) BLUE_SPEAKER_POSE = get_fiducial_pose(7) FIELD_WIDTH = 8.0161 FIELD_LENGTH = RED_SPEAKER_POSE.x + BLUE_SPEAKER_POSE.x -# Minimum height of the overhanging speaker hood as obtained from a field Onshape model. -SPEAKER_HOOD_HEIGHT = 2.104883 -SPEAKER_HOOD_WIDTH = 1.05 -SPEAKER_HOOD_DEPTH = 0.456499 - -BLUE_SPEAKER_TARGET_POSITION = BLUE_SPEAKER_POSE.translation() + Translation3d( - SPEAKER_HOOD_DEPTH, 0, 0 -) - -RED_SPEAKER_TARGET_POSITION = RED_SPEAKER_POSE.translation() - Translation3d( - SPEAKER_HOOD_DEPTH, 0, 0 -) - -NOTE_DIAMETER = 0.0254 * 14 - def field_flip_pose2d(p: Pose2d): return Pose2d( @@ -70,14 +56,3 @@ def field_flip_translation2d(t: Translation2d): # This will default to the blue alliance if a proper link to the driver station has not yet been established def is_red() -> bool: return wpilib.DriverStation.getAlliance() == wpilib.DriverStation.Alliance.kRed - - -def get_goal_speaker_position() -> Translation3d: - if is_red(): - return RED_SPEAKER_POSE.translation() - - return BLUE_SPEAKER_POSE.translation() - - -def translation_to_goal(position: Translation2d) -> Translation2d: - return get_goal_speaker_position().toTranslation2d() - position diff --git a/utilities/position.py b/utilities/position.py deleted file mode 100644 index f423bb91..00000000 --- a/utilities/position.py +++ /dev/null @@ -1,91 +0,0 @@ -import math - -from wpimath.geometry import Rotation2d, Translation2d, Pose2d - -from utilities.game import ( - RED_SPEAKER_POSE, - BLUE_SPEAKER_POSE, - field_flip_pose2d, - field_flip_translation2d, - field_flip_angle, -) - - -class Path: - waypoints: list[Translation2d] - final_heading: float - face_target: bool - - def __init__(self, waypoints: list[Translation2d], face_target: bool): - self.waypoints = waypoints - self.face_target = face_target - if face_target: - last_waypoint = waypoints[-1] - self.final_heading = ( - ( - BLUE_SPEAKER_POSE.translation().toTranslation2d() - - field_flip_translation2d(last_waypoint) - ) - .angle() - .radians() - ) - self.final_heading = field_flip_angle(self.final_heading) + math.pi - else: - self.final_heading = 0 - - -stage_tolerance = 0.4 - - -class NotePositions: - # These are the 3 close notes, named for the nearest element - amp = Translation2d(13.645, 7.00045) - speaker = Translation2d(13.645, 5.55265) - podium = Translation2d(13.645, 4.1057) - - # 1 is always the closest to the amp side - Centre1 = Translation2d(8.2956, 7.4585) - Centre2 = Translation2d(8.2956, 5.7821) - Centre3 = Translation2d(8.2956, 4.1057) - Centre4 = Translation2d(8.2956, 2.4293) - Centre5 = Translation2d(8.2956, 0.75286) - - # The podium note is very close to the stage leg so we need different positions to avoid collisions - # Directions are in the field coordinate system for red side - podium_N = podium + Translation2d(stage_tolerance, 0) - podium_NW = podium + Translation2d( - stage_tolerance / math.sqrt(2), stage_tolerance / math.sqrt(2) - ) - podium_NE = podium + Translation2d( - stage_tolerance / math.sqrt(2), -stage_tolerance / math.sqrt(2) - ) - - -class ShootingPositions: - close_straight = Translation2d(15, RED_SPEAKER_POSE.y) - amp_speaker_bounce = Translation2d( - 14.7, (NotePositions.amp.y + NotePositions.speaker.y) / 2 - ) - source_side = Translation2d(15.556, 4.034) - - -class TeamPoses: - RED_TEST_POSE = Pose2d(15.1, 5.5, math.pi) - BLUE_TEST_POSE = field_flip_pose2d(RED_TEST_POSE) - BLUE_PODIUM = Pose2d(Translation2d(2.992, 4.08455), Rotation2d(math.pi)) - RED_PODIUM = field_flip_pose2d(BLUE_PODIUM) - RED_AMP_START_POSE = Pose2d(15.9, 6.7, math.pi) - - -def distance_between(intended_start_pose: Pose2d, current_pose: Pose2d) -> float: - return (intended_start_pose.translation() - current_pose.translation()).norm() - - -class PathPositions: - stage_transition_N = Translation2d(11.4, 4.5) - stage_transition_S = Translation2d(11.4, 3.74) - stage_transition_S_entry = Translation2d(13.0, 2.5) - avoid_wall = Translation2d(10.80, 6.55) - avoid_stage_S = Translation2d(11.66, 1.40) - avoid_starting_faults = Translation2d(14.429, 2.946) - enforce_pickup_angle = Translation2d(9.6, 1.6) From 44216b07c37150309d3d8a3a24c79dd947896053 Mon Sep 17 00:00:00 2001 From: Beana1234 Date: Tue, 22 Oct 2024 20:53:51 +1100 Subject: [PATCH 18/20] add positon file --- utilities/position.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 utilities/position.py diff --git a/utilities/position.py b/utilities/position.py new file mode 100644 index 00000000..44556dc2 --- /dev/null +++ b/utilities/position.py @@ -0,0 +1,8 @@ +import math +from wpimath.geometry import Pose2d +from utilities.game import field_flip_pose2d + + +class TeamPoses: + RED_TEST_POSE = Pose2d(15.1, 5.5, math.pi) + BLUE_TEST_POSE = field_flip_pose2d(RED_TEST_POSE) From 0761981b13dc3da1145b37df7e39c41b471a78dc Mon Sep 17 00:00:00 2001 From: Beana1234 Date: Tue, 22 Oct 2024 21:02:47 +1100 Subject: [PATCH 19/20] brought back team poses along with todos to remove or update with new season --- components/chassis.py | 3 +++ utilities/position.py | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/components/chassis.py b/components/chassis.py index 27dd0bff..01dc8e29 100644 --- a/components/chassis.py +++ b/components/chassis.py @@ -311,6 +311,7 @@ def get_module_states( ) def setup(self) -> None: + # TODO update with new game info initial_pose = TeamPoses.RED_TEST_POSE if is_red() else TeamPoses.BLUE_TEST_POSE self.estimator = SwerveDrive4PoseEstimator( @@ -418,6 +419,7 @@ def update_alliance(self) -> None: # If so, it means we have an update from the FMS and need to re-init the odom if is_red() != self.on_red_alliance: self.on_red_alliance = is_red() + # TODO update with new game info if self.on_red_alliance: self.set_pose(TeamPoses.RED_TEST_POSE) else: @@ -450,6 +452,7 @@ def reset_yaw(self) -> None: def reset_odometry(self) -> None: """Reset odometry to current team's podium""" + # TODO update with new game info if is_red(): self.set_pose(TeamPoses.RED_PODIUM) else: diff --git a/utilities/position.py b/utilities/position.py index 44556dc2..44ef4206 100644 --- a/utilities/position.py +++ b/utilities/position.py @@ -1,8 +1,11 @@ import math -from wpimath.geometry import Pose2d +from wpimath.geometry import Pose2d, Translation2d, Rotation2d from utilities.game import field_flip_pose2d +# TODO update with new game info class TeamPoses: RED_TEST_POSE = Pose2d(15.1, 5.5, math.pi) BLUE_TEST_POSE = field_flip_pose2d(RED_TEST_POSE) + BLUE_PODIUM = Pose2d(Translation2d(2.992, 4.08455), Rotation2d(math.pi)) + RED_PODIUM = field_flip_pose2d(BLUE_PODIUM) From df614d37f3af846dd0c33fc6589d0409ec042232 Mon Sep 17 00:00:00 2001 From: Beana1234 Date: Tue, 22 Oct 2024 21:04:55 +1100 Subject: [PATCH 20/20] add init file to components directory --- components/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 components/__init__.py diff --git a/components/__init__.py b/components/__init__.py new file mode 100644 index 00000000..e69de29b