diff --git a/.gitignore b/.gitignore index c85c4b9b..74acd7d6 100644 --- a/.gitignore +++ b/.gitignore @@ -165,3 +165,9 @@ cython_debug/ # Joe's not sure what this is for, put it back in the tree only if needed. networktables.json + +# Add to tree but only when neccicary (adding a map or smthn) +simgui-window.json + +# sysid ignores +*.SysId diff --git a/rio/Makefile b/rio/Makefile index 711762c1..71faa9a4 100644 --- a/rio/Makefile +++ b/rio/Makefile @@ -13,22 +13,21 @@ help: ## Prints this help message sim: ## Run the simulator python -m robotpy sim - -deploy: ## Deploy to the robot (with console) +deploy: ## Deploy to the robot (with netconsole) python -m robotpy deploy --nc - -push: ## Deploy to the robot (push only, no console) +push: ## Deploy to the robot (push only, no netconsole) python -m robotpy deploy - download: ## Download robot requirements locally - robotpy-installer download -r robot_requirements.txt - + python -m robotpy installer download -r robot_requirements.txt + python -m robotpy installer download-python install: ## Install requirements, run download first! - robotpy-installer install -r robot_requirements.txt + python -m robotpy installer install -r robot_requirements.txt +sync: ## Sync robotpy requirements + python -m robotpy sync info: ## Shortcut to get information about the code already on the bot python -m robotpy deploy-info @@ -37,10 +36,10 @@ test: ## Run automated tests python -m robotpy test download-python: ## Download python (for robot) - robotpy-installer download-python + python -m robotpy installer download-python install-python: ## Install python (for robot) - robotpy-installer install-python + python -m robotpy installer install-python clean: ## Clean the repo git clean -fdX diff --git a/rio/Pipfile b/rio/Pipfile index f41ec308..ef016fa0 100644 --- a/rio/Pipfile +++ b/rio/Pipfile @@ -4,16 +4,14 @@ verify_ssl = true name = "pypi" [packages] -robotpy = {extras = ["rev", "ctre", "commands2", "navx"]} wpilib = {extras = ["all"]} -pyyaml = "6.0" -black = "*" +robotpy = "2024.2.1.1" +robotpy-rev = "2024.2.0" +robotpy-ctre = "2024.1.1" +robotpy-navx = "2024.1.0" +robotpy-commands-v2 = "2024.2.1" [dev-packages] -black = "*" [requires] python_version = "3.11" - -[pipenv] -allow_prereleases = true \ No newline at end of file diff --git a/rio/Pipfile.lock b/rio/Pipfile.lock index 43f1ce91..297c08a6 100644 --- a/rio/Pipfile.lock +++ b/rio/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "293af6cc7b8c4bebe8af1addf8af658e86c86729bf6846a84d8814d1d57b0fa0" + "sha256": "ff968964e7b21e108cc95483cffcf81867e8703894b999f7be450e352f4ecd64" }, "pipfile-spec": 6, "requires": { @@ -16,103 +16,6 @@ ] }, "default": { - "aiohttp": { - "hashes": [ - "sha256:02ab6006ec3c3463b528374c4cdce86434e7b89ad355e7bf29e2f16b46c7dd6f", - "sha256:04fa38875e53eb7e354ece1607b1d2fdee2d175ea4e4d745f6ec9f751fe20c7c", - "sha256:0b0a6a36ed7e164c6df1e18ee47afbd1990ce47cb428739d6c99aaabfaf1b3af", - "sha256:0d406b01a9f5a7e232d1b0d161b40c05275ffbcbd772dc18c1d5a570961a1ca4", - "sha256:0e49b08eafa4f5707ecfb321ab9592717a319e37938e301d462f79b4e860c32a", - "sha256:0e7ba7ff228c0d9a2cd66194e90f2bca6e0abca810b786901a569c0de082f489", - "sha256:11cb254e397a82efb1805d12561e80124928e04e9c4483587ce7390b3866d213", - "sha256:11ff168d752cb41e8492817e10fb4f85828f6a0142b9726a30c27c35a1835f01", - "sha256:176df045597e674fa950bf5ae536be85699e04cea68fa3a616cf75e413737eb5", - "sha256:219a16763dc0294842188ac8a12262b5671817042b35d45e44fd0a697d8c8361", - "sha256:22698f01ff5653fe66d16ffb7658f582a0ac084d7da1323e39fd9eab326a1f26", - "sha256:237533179d9747080bcaad4d02083ce295c0d2eab3e9e8ce103411a4312991a0", - "sha256:289ba9ae8e88d0ba16062ecf02dd730b34186ea3b1e7489046fc338bdc3361c4", - "sha256:2c59e0076ea31c08553e868cec02d22191c086f00b44610f8ab7363a11a5d9d8", - "sha256:2c9376e2b09895c8ca8b95362283365eb5c03bdc8428ade80a864160605715f1", - "sha256:3135713c5562731ee18f58d3ad1bf41e1d8883eb68b363f2ffde5b2ea4b84cc7", - "sha256:3b9c7426923bb7bd66d409da46c41e3fb40f5caf679da624439b9eba92043fa6", - "sha256:3c0266cd6f005e99f3f51e583012de2778e65af6b73860038b968a0a8888487a", - "sha256:41473de252e1797c2d2293804e389a6d6986ef37cbb4a25208de537ae32141dd", - "sha256:4831df72b053b1eed31eb00a2e1aff6896fb4485301d4ccb208cac264b648db4", - "sha256:49f0c1b3c2842556e5de35f122fc0f0b721334ceb6e78c3719693364d4af8499", - "sha256:4b4c452d0190c5a820d3f5c0f3cd8a28ace48c54053e24da9d6041bf81113183", - "sha256:4ee8caa925aebc1e64e98432d78ea8de67b2272252b0a931d2ac3bd876ad5544", - "sha256:500f1c59906cd142d452074f3811614be04819a38ae2b3239a48b82649c08821", - "sha256:5216b6082c624b55cfe79af5d538e499cd5f5b976820eac31951fb4325974501", - "sha256:54311eb54f3a0c45efb9ed0d0a8f43d1bc6060d773f6973efd90037a51cd0a3f", - "sha256:54631fb69a6e44b2ba522f7c22a6fb2667a02fd97d636048478db2fd8c4e98fe", - "sha256:565760d6812b8d78d416c3c7cfdf5362fbe0d0d25b82fed75d0d29e18d7fc30f", - "sha256:598db66eaf2e04aa0c8900a63b0101fdc5e6b8a7ddd805c56d86efb54eb66672", - "sha256:5c4fa235d534b3547184831c624c0b7c1e262cd1de847d95085ec94c16fddcd5", - "sha256:69985d50a2b6f709412d944ffb2e97d0be154ea90600b7a921f95a87d6f108a2", - "sha256:69da0f3ed3496808e8cbc5123a866c41c12c15baaaead96d256477edf168eb57", - "sha256:6c93b7c2e52061f0925c3382d5cb8980e40f91c989563d3d32ca280069fd6a87", - "sha256:70907533db712f7aa791effb38efa96f044ce3d4e850e2d7691abd759f4f0ae0", - "sha256:81b77f868814346662c96ab36b875d7814ebf82340d3284a31681085c051320f", - "sha256:82eefaf1a996060602f3cc1112d93ba8b201dbf5d8fd9611227de2003dddb3b7", - "sha256:85c3e3c9cb1d480e0b9a64c658cd66b3cfb8e721636ab8b0e746e2d79a7a9eed", - "sha256:8a22a34bc594d9d24621091d1b91511001a7eea91d6652ea495ce06e27381f70", - "sha256:8cef8710fb849d97c533f259103f09bac167a008d7131d7b2b0e3a33269185c0", - "sha256:8d44e7bf06b0c0a70a20f9100af9fcfd7f6d9d3913e37754c12d424179b4e48f", - "sha256:8d7f98fde213f74561be1d6d3fa353656197f75d4edfbb3d94c9eb9b0fc47f5d", - "sha256:8d8e4450e7fe24d86e86b23cc209e0023177b6d59502e33807b732d2deb6975f", - "sha256:8fc49a87ac269d4529da45871e2ffb6874e87779c3d0e2ccd813c0899221239d", - "sha256:90ec72d231169b4b8d6085be13023ece8fa9b1bb495e4398d847e25218e0f431", - "sha256:91c742ca59045dce7ba76cab6e223e41d2c70d79e82c284a96411f8645e2afff", - "sha256:9b05d33ff8e6b269e30a7957bd3244ffbce2a7a35a81b81c382629b80af1a8bf", - "sha256:9b05d5cbe9dafcdc733262c3a99ccf63d2f7ce02543620d2bd8db4d4f7a22f83", - "sha256:9c5857612c9813796960c00767645cb5da815af16dafb32d70c72a8390bbf690", - "sha256:a34086c5cc285be878622e0a6ab897a986a6e8bf5b67ecb377015f06ed316587", - "sha256:ab221850108a4a063c5b8a70f00dd7a1975e5a1713f87f4ab26a46e5feac5a0e", - "sha256:b796b44111f0cab6bbf66214186e44734b5baab949cb5fb56154142a92989aeb", - "sha256:b8c3a67eb87394386847d188996920f33b01b32155f0a94f36ca0e0c635bf3e3", - "sha256:bcb6532b9814ea7c5a6a3299747c49de30e84472fa72821b07f5a9818bce0f66", - "sha256:bcc0ea8d5b74a41b621ad4a13d96c36079c81628ccc0b30cfb1603e3dfa3a014", - "sha256:bea94403a21eb94c93386d559bce297381609153e418a3ffc7d6bf772f59cc35", - "sha256:bff7e2811814fa2271be95ab6e84c9436d027a0e59665de60edf44e529a42c1f", - "sha256:c72444d17777865734aa1a4d167794c34b63e5883abb90356a0364a28904e6c0", - "sha256:c7b5d5d64e2a14e35a9240b33b89389e0035e6de8dbb7ffa50d10d8b65c57449", - "sha256:c7e939f1ae428a86e4abbb9a7c4732bf4706048818dfd979e5e2839ce0159f23", - "sha256:c88a15f272a0ad3d7773cf3a37cc7b7d077cbfc8e331675cf1346e849d97a4e5", - "sha256:c9110c06eaaac7e1f5562caf481f18ccf8f6fdf4c3323feab28a93d34cc646bd", - "sha256:ca7ca5abfbfe8d39e653870fbe8d7710be7a857f8a8386fc9de1aae2e02ce7e4", - "sha256:cae4c0c2ca800c793cae07ef3d40794625471040a87e1ba392039639ad61ab5b", - "sha256:cdefe289681507187e375a5064c7599f52c40343a8701761c802c1853a504558", - "sha256:cf2a0ac0615842b849f40c4d7f304986a242f1e68286dbf3bd7a835e4f83acfd", - "sha256:cfeadf42840c1e870dc2042a232a8748e75a36b52d78968cda6736de55582766", - "sha256:d737e69d193dac7296365a6dcb73bbbf53bb760ab25a3727716bbd42022e8d7a", - "sha256:d7481f581251bb5558ba9f635db70908819caa221fc79ee52a7f58392778c636", - "sha256:df9cf74b9bc03d586fc53ba470828d7b77ce51b0582d1d0b5b2fb673c0baa32d", - "sha256:e1f80197f8b0b846a8d5cf7b7ec6084493950d0882cc5537fb7b96a69e3c8590", - "sha256:ecca113f19d5e74048c001934045a2b9368d77b0b17691d905af18bd1c21275e", - "sha256:ee2527134f95e106cc1653e9ac78846f3a2ec1004cf20ef4e02038035a74544d", - "sha256:f27fdaadce22f2ef950fc10dcdf8048407c3b42b73779e48a4e76b3c35bca26c", - "sha256:f694dc8a6a3112059258a725a4ebe9acac5fe62f11c77ac4dcf896edfa78ca28", - "sha256:f800164276eec54e0af5c99feb9494c295118fc10a11b997bbb1348ba1a52065", - "sha256:ffcd828e37dc219a72c9012ec44ad2e7e3066bec6ff3aaa19e7d435dbf4032ca" - ], - "version": "==3.9.1" - }, - "aiosignal": { - "hashes": [ - "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc", - "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17" - ], - "markers": "python_version >= '3.7'", - "version": "==1.3.1" - }, - "attrs": { - "hashes": [ - "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30", - "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1" - ], - "markers": "python_version >= '3.7'", - "version": "==23.2.0" - }, "bcrypt": { "hashes": [ "sha256:02d9ef8915f72dd6daaef40e0baeef8a017ce624369f09754baf32bb32dba25f", @@ -146,35 +49,6 @@ "markers": "python_version >= '3.7'", "version": "==4.1.2" }, - "black": { - "hashes": [ - "sha256:2220c470c22476ca9631337b0daae41be2b215599919b19d576a956ad38aca69", - "sha256:2a12829e372563ffff10c18c7aff1ef274da6afbc7bc8ccdb5fcc8ff84cab43f", - "sha256:3d139b9531e6bb6d129497a46475535d8289dddc861a5b980f908c36597b9817", - "sha256:41c0ce5cbdb701900c166bcca08ac941b64cf1d6967509e3caeab126da0ae0d0", - "sha256:4a159ae57f239f3f1ef6a78784b00c1c617c7bb188cc351b3017b9e0702df11c", - "sha256:4de8ba5825588017f90e63d7a25fc4df33a6342d1f4d628ad76130d8f4488fc6", - "sha256:623efdb54e7290ba75f7b822dfd2d8a47a55e721ae63aab671ccfd46b2ba6c5d", - "sha256:6b594b3ede60182215d258c76de2de64712d2e8424442ff4402276e22684abbe", - "sha256:6e3c74b35ea179bb69440286b81c309a64c34a032746a9eef3399dc3ce671352", - "sha256:87c8165fad00b03d9c1d400b1dd250479792f49d012807ee45162d323d04fc06", - "sha256:88d1c60bac2044a409154e895abb9d74c8ff5d034fb70f3e1f7c3ae96206bc0c", - "sha256:915a6b6b916fc66edec886fc71b60284e447d8fa39d22b879af7ae6efccca90f", - "sha256:a2c977909557439d0f17dc82adaea84e48374950d53416efc0b8451a594d42c3", - "sha256:ac226f37fc429b386d6447df6256dc958c28dd602f86f950072febf886995f80", - "sha256:b03cdf8a4e15929adf47e5e40a0ddeea1d63b65cf59c22553c12417a0c7ccbf4", - "sha256:c86ecd9d3da3d91e96da5f4a43d9c4fe35c5698b0633e91f171ba9468d112a8b", - "sha256:cad114d8673adab76b3602c28c461c613b7be3da28415500e42aed47415eb561", - "sha256:cb0a7ea9aa1c108924e31f1204a1e2534af255dbaa24ecbb8c05f47341a7b6f1", - "sha256:d30a018fc03fd1e83c75d40b8a156ef541d0b56b6403b63754e1cc96889849d9", - "sha256:d47b6530c55c092a9d841a12c8b3ad838bd639bebf6660a3df9dae83d4ab83c1", - "sha256:e8a054dbb8947718820be2ed6953d66b912ec2795f282725efdd08381a11b0d0", - "sha256:ec345caf15ae2c61540812500979e92f2989c6b6d4d13d21bdc82908043b3265" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==24.1a1" - }, "cffi": { "hashes": [ "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc", @@ -230,136 +104,46 @@ "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956", "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357" ], - "markers": "python_version >= '3.8'", + "markers": "platform_python_implementation != 'PyPy'", "version": "==1.16.0" }, - "click": { - "hashes": [ - "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", - "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" - ], - "markers": "python_version >= '3.7'", - "version": "==8.1.7" - }, "cryptography": { "hashes": [ - "sha256:079b85658ea2f59c4f43b70f8119a52414cdb7be34da5d019a77bf96d473b960", - "sha256:09616eeaef406f99046553b8a40fbf8b1e70795a91885ba4c96a70793de5504a", - "sha256:13f93ce9bea8016c253b34afc6bd6a75993e5c40672ed5405a9c832f0d4a00bc", - "sha256:37a138589b12069efb424220bf78eac59ca68b95696fc622b6ccc1c0a197204a", - "sha256:3c78451b78313fa81607fa1b3f1ae0a5ddd8014c38a02d9db0616133987b9cdf", - "sha256:43f2552a2378b44869fe8827aa19e69512e3245a219104438692385b0ee119d1", - "sha256:48a0476626da912a44cc078f9893f292f0b3e4c739caf289268168d8f4702a39", - "sha256:49f0805fc0b2ac8d4882dd52f4a3b935b210935d500b6b805f321addc8177406", - "sha256:5429ec739a29df2e29e15d082f1d9ad683701f0ec7709ca479b3ff2708dae65a", - "sha256:5a1b41bc97f1ad230a41657d9155113c7521953869ae57ac39ac7f1bb471469a", - "sha256:68a2dec79deebc5d26d617bfdf6e8aab065a4f34934b22d3b5010df3ba36612c", - "sha256:7a698cb1dac82c35fcf8fe3417a3aaba97de16a01ac914b89a0889d364d2f6be", - "sha256:841df4caa01008bad253bce2a6f7b47f86dc9f08df4b433c404def869f590a15", - "sha256:90452ba79b8788fa380dfb587cca692976ef4e757b194b093d845e8d99f612f2", - "sha256:928258ba5d6f8ae644e764d0f996d61a8777559f72dfeb2eea7e2fe0ad6e782d", - "sha256:af03b32695b24d85a75d40e1ba39ffe7db7ffcb099fe507b39fd41a565f1b157", - "sha256:b640981bf64a3e978a56167594a0e97db71c89a479da8e175d8bb5be5178c003", - "sha256:c5ca78485a255e03c32b513f8c2bc39fedb7f5c5f8535545bdc223a03b24f248", - "sha256:c7f3201ec47d5207841402594f1d7950879ef890c0c495052fa62f58283fde1a", - "sha256:d5ec85080cce7b0513cfd233914eb8b7bbd0633f1d1703aa28d1dd5a72f678ec", - "sha256:d6c391c021ab1f7a82da5d8d0b3cee2f4b2c455ec86c8aebbc84837a631ff309", - "sha256:e3114da6d7f95d2dee7d3f4eec16dacff819740bbab931aff8648cb13c5ff5e7", - "sha256:f983596065a18a2183e7f79ab3fd4c475205b839e02cbc0efbbf9666c4b3083d" + "sha256:0a68bfcf57a6887818307600c3c0ebc3f62fbb6ccad2240aa21887cda1f8df1b", + "sha256:146e971e92a6dd042214b537a726c9750496128453146ab0ee8971a0299dc9bd", + "sha256:14e4b909373bc5bf1095311fa0f7fcabf2d1a160ca13f1e9e467be1ac4cbdf94", + "sha256:206aaf42e031b93f86ad60f9f5d9da1b09164f25488238ac1dc488334eb5e221", + "sha256:3005166a39b70c8b94455fdbe78d87a444da31ff70de3331cdec2c568cf25b7e", + "sha256:324721d93b998cb7367f1e6897370644751e5580ff9b370c0a50dc60a2003513", + "sha256:33588310b5c886dfb87dba5f013b8d27df7ffd31dc753775342a1e5ab139e59d", + "sha256:35cf6ed4c38f054478a9df14f03c1169bb14bd98f0b1705751079b25e1cb58bc", + "sha256:3ca482ea80626048975360c8e62be3ceb0f11803180b73163acd24bf014133a0", + "sha256:56ce0c106d5c3fec1038c3cca3d55ac320a5be1b44bf15116732d0bc716979a2", + "sha256:5a217bca51f3b91971400890905a9323ad805838ca3fa1e202a01844f485ee87", + "sha256:678cfa0d1e72ef41d48993a7be75a76b0725d29b820ff3cfd606a5b2b33fda01", + "sha256:69fd009a325cad6fbfd5b04c711a4da563c6c4854fc4c9544bff3088387c77c0", + "sha256:6cf9b76d6e93c62114bd19485e5cb003115c134cf9ce91f8ac924c44f8c8c3f4", + "sha256:74f18a4c8ca04134d2052a140322002fef535c99cdbc2a6afc18a8024d5c9d5b", + "sha256:85f759ed59ffd1d0baad296e72780aa62ff8a71f94dc1ab340386a1207d0ea81", + "sha256:87086eae86a700307b544625e3ba11cc600c3c0ef8ab97b0fda0705d6db3d4e3", + "sha256:8814722cffcfd1fbd91edd9f3451b88a8f26a5fd41b28c1c9193949d1c689dc4", + "sha256:8fedec73d590fd30c4e3f0d0f4bc961aeca8390c72f3eaa1a0874d180e868ddf", + "sha256:9515ea7f596c8092fdc9902627e51b23a75daa2c7815ed5aa8cf4f07469212ec", + "sha256:988b738f56c665366b1e4bfd9045c3efae89ee366ca3839cd5af53eaa1401bce", + "sha256:a2a8d873667e4fd2f34aedab02ba500b824692c6542e017075a2efc38f60a4c0", + "sha256:bd7cf7a8d9f34cc67220f1195884151426ce616fdc8285df9054bfa10135925f", + "sha256:bdce70e562c69bb089523e75ef1d9625b7417c6297a76ac27b1b8b1eb51b7d0f", + "sha256:be14b31eb3a293fc6e6aa2807c8a3224c71426f7c4e3639ccf1a2f3ffd6df8c3", + "sha256:be41b0c7366e5549265adf2145135dca107718fa44b6e418dc7499cfff6b4689", + "sha256:c310767268d88803b653fffe6d6f2f17bb9d49ffceb8d70aed50ad45ea49ab08", + "sha256:c58115384bdcfe9c7f644c72f10f6f42bed7cf59f7b52fe1bf7ae0a622b3a139", + "sha256:c640b0ef54138fde761ec99a6c7dc4ce05e80420262c20fa239e694ca371d434", + "sha256:ca20550bb590db16223eb9ccc5852335b48b8f597e2f6f0878bbfd9e7314eb17", + "sha256:d97aae66b7de41cdf5b12087b5509e4e9805ed6f562406dfcf60e8481a9a28f8", + "sha256:e9326ca78111e4c645f7e49cbce4ed2f3f85e17b61a563328c85a5208cf34440" ], "markers": "python_version >= '3.7'", - "version": "==41.0.7" - }, - "frozenlist": { - "hashes": [ - "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7", - "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98", - "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad", - "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5", - "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae", - "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e", - "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a", - "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701", - "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d", - "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6", - "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6", - "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106", - "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75", - "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868", - "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a", - "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0", - "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1", - "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826", - "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec", - "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6", - "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950", - "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19", - "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0", - "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8", - "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a", - "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09", - "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86", - "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c", - "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5", - "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b", - "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b", - "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d", - "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0", - "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea", - "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776", - "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a", - "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897", - "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7", - "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09", - "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9", - "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe", - "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd", - "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742", - "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09", - "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0", - "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932", - "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1", - "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a", - "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49", - "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d", - "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7", - "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480", - "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89", - "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e", - "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b", - "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82", - "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb", - "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068", - "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8", - "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b", - "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb", - "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2", - "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11", - "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b", - "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc", - "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0", - "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497", - "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17", - "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0", - "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2", - "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439", - "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5", - "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac", - "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825", - "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887", - "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced", - "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74" - ], - "markers": "python_version >= '3.8'", - "version": "==1.4.1" - }, - "idna": { - "hashes": [ - "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca", - "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f" - ], - "markers": "python_version >= '3.5'", - "version": "==3.6" + "version": "==42.0.0" }, "iniconfig": { "hashes": [ @@ -369,94 +153,6 @@ "markers": "python_version >= '3.7'", "version": "==2.0.0" }, - "multidict": { - "hashes": [ - "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9", - "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8", - "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03", - "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710", - "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161", - "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664", - "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569", - "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067", - "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313", - "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706", - "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2", - "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636", - "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49", - "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93", - "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603", - "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0", - "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60", - "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4", - "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e", - "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1", - "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60", - "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951", - "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc", - "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe", - "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95", - "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d", - "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8", - "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed", - "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2", - "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775", - "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87", - "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c", - "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2", - "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98", - "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3", - "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe", - "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78", - "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660", - "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176", - "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e", - "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988", - "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c", - "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c", - "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0", - "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449", - "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f", - "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde", - "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5", - "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d", - "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac", - "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a", - "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9", - "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca", - "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11", - "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35", - "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063", - "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b", - "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982", - "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258", - "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1", - "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52", - "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480", - "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7", - "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461", - "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d", - "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc", - "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779", - "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a", - "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547", - "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0", - "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171", - "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf", - "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d", - "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba" - ], - "markers": "python_version >= '3.7'", - "version": "==6.0.4" - }, - "mypy-extensions": { - "hashes": [ - "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", - "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782" - ], - "markers": "python_version >= '3.5'", - "version": "==1.0.0" - }, "packaging": { "hashes": [ "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", @@ -473,13 +169,16 @@ "markers": "python_version >= '3.6'", "version": "==3.4.0" }, - "pathspec": { + "phoenix6": { "hashes": [ - "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", - "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712" + "sha256:48f79760706515157512d4596a2964c327235da53dd7b4cadbc50c4bd61b3b65", + "sha256:4aa88861786861aa647193052da0df0d8f26a91cabfa5e84d85fa71af0de649b", + "sha256:65b687a22b462e48db0e02224f43b641a9a8d4df7c7c06cdf60da097fce8be60", + "sha256:c3c75782066665be9d37d3641c061be4bf1460e838f482c8f5723e754080ba76", + "sha256:c70dce1831afd224e10705483d1e383817bd58ff604cf139d64ba7bb8f9f5df8" ], - "markers": "python_version >= '3.8'", - "version": "==0.12.1" + "markers": "python_version >= '3.7' and python_version < '4'", + "version": "==24.1.0" }, "pint": { "hashes": [ @@ -489,21 +188,13 @@ "markers": "python_version >= '3.9'", "version": "==0.23" }, - "platformdirs": { - "hashes": [ - "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380", - "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420" - ], - "markers": "python_version >= '3.8'", - "version": "==4.1.0" - }, "pluggy": { "hashes": [ - "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12", - "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7" + "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981", + "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be" ], "markers": "python_version >= '3.8'", - "version": "==1.3.0" + "version": "==1.4.0" }, "pycparser": { "hashes": [ @@ -514,11 +205,11 @@ }, "pyfrc": { "hashes": [ - "sha256:62438a558cb8b467c09836c92fd9d1f283523db1a1f757233c906dae85261886", - "sha256:6d174996fea8b7c74f6b5ef841da3d73397c8c74953ec1ae23a33983471413bc" + "sha256:011076dbc62606b08eec6eb1bb30497d085d34cb71537a7ce0d06f44c8492855", + "sha256:2386be296bfb7e482a26c25e85ee61495ea10154f920d7450fec575defb8cc05" ], "markers": "platform_machine != 'roborio' and platform_machine != 'armv7l' and platform_machine != 'aarch64'", - "version": "==2024.0.0b3" + "version": "==2024.0.1" }, "pynacl": { "hashes": [ @@ -546,32 +237,32 @@ }, "pyntcore": { "hashes": [ - "sha256:157a6c6afac6d0570d9fd44c2b73eb955316b5226f3c2233d0e0b8b64d2eea61", - "sha256:17b5aec1b58f4b9ea568302df6d909092dbcc6090ddb894bf3c47d5aa8029b53", - "sha256:2c1c16fe7b61a0d4f805dd0d2a2a6a2036240ffdac09de8b2e8dd482bf86284a", - "sha256:38f894cb13288da6ac2e828fcfca5d87d2284a6015a96d203cf5419f4d4a8d4c", - "sha256:734291d41879a85ac287b342110adb363ca4bbc90844dbe156d66b6997f46e2e", - "sha256:8ae32804ec565016819edaddc83dd94c1a1e30b2d78a6b3c17dee5da665f6773", - "sha256:8d61d179266c48086562a6f5e4adf176366fe98445e1c655562bfc1a15982867", - "sha256:9ab05d23171c5383c78904af34689f32490c47e5596b16753ec30f1f1d7e2573", - "sha256:a229860cff660ccff02c5e3de7b9a461de523950f7c0c75e3f705cc312888c12", - "sha256:aff310a14720904b1c0d57e1c7cf700d99c2add5859c485147da63ae184dec27", - "sha256:b7ead99b9743dd881ba907e02d85d890222de3f035573f96aa4dd1bdd7962c0c", - "sha256:b8a188ca9ed14264dd12cce17a425c9d75e47d65dbf20a174824ab2541f401c3", - "sha256:c0127914b4b31b88e477696a20214711c9450f46f44ca330977fbd9a598a34e3", - "sha256:cb797a0ecbfc8d572593a815aadc32cd23a28f2655fef29840e949c3899152c8", - "sha256:e76e02582c53868b162c9de8680b3799cf53ffb7bbe03b69ef6bd9053583f715" + "sha256:10b0d9a39b6a0dc92f25ae06798a5dcb1eb36ed5fc07083711cce39056ac62ab", + "sha256:13bfacc40106929e9225acc4fb4638e60e4b119435eb65e100e645af50e3b25e", + "sha256:171015482d904817cac66d4a8a2a9efaa9bf3af52f23a6729f687c7a9a22fcd9", + "sha256:45fb06fc5ffb1a995bd5c583866dd029a9ef95819dc33f91766ac235203bc103", + "sha256:56cfb02826e266da6c1ed563d8291d8e4c20c2eb928adc52cca1b43f27d55261", + "sha256:5c8dfb93756c7d945e88d34a2bda9c51f83478cf89e7bd8049d13a3dc9882373", + "sha256:6b8a093cc8ff8f436ddbd83a6b2c2cf0184001d137df2c1e708f19814aa1f65b", + "sha256:701e0b4aece667e286ca4e772fc75fb5cb69fa0458db3b53687cc9aeb0b180f8", + "sha256:8e2d05b55b8c5f01f11016d4e400f2242b4becf7ca26783821c7682a98aae8ea", + "sha256:9abf53adb8a412f9584b14f3a9dabd37940af5f57ff3c60ff5f2b150bf747e3a", + "sha256:b137734c8f4083827079665cd34460863c57c9ddd6b397726a6eb9734cb255ca", + "sha256:dfdcde81b621bd6fee02185c75bcdd4d180de1d3b281df70213b8f8784580dca", + "sha256:e30dd12eafd0d28e306c3076cf99b067347a9c0fbe299f82553a7b0a94c056ab", + "sha256:f06762dd96eed6a5b79ff07c46fab92bab08edfe0788b0265e0720e747f6afa4", + "sha256:fc174b121f984b876cc3322129de7a475155027304f43867ca11e6441d101149" ], "markers": "python_version >= '3.8'", - "version": "==2024.0.0b4.post1" + "version": "==2024.2.1.2" }, "pytest": { "hashes": [ - "sha256:6c30d4c4409c5d227ef936678b72c56b6fbaed28a6ee4eafd2c93ed9a24c65af", - "sha256:b5baeee6fb27cbca444fc1bab2ee7e1934f93daa50a4d475a6d0f819c263e573" + "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280", + "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8" ], - "markers": "python_version >= '3.8'", - "version": "==8.0.0rc1" + "markers": "python_version >= '3.7'", + "version": "==7.4.4" }, "pytest-reraise": { "hashes": [ @@ -581,66 +272,14 @@ "markers": "python_full_version >= '3.6.1' and python_full_version < '4.0.0'", "version": "==2.1.2" }, - "pyyaml": { - "hashes": [ - "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf", - "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293", - "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b", - "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57", - "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b", - "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4", - "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07", - "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba", - "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9", - "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287", - "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513", - "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0", - "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782", - "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0", - "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92", - "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f", - "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2", - "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc", - "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1", - "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c", - "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86", - "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4", - "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c", - "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34", - "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b", - "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d", - "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c", - "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb", - "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7", - "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737", - "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3", - "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d", - "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358", - "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53", - "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78", - "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803", - "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a", - "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f", - "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174", - "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==6.0" - }, "robotpy": { - "extras": [ - "commands2", - "ctre", - "navx", - "rev" - ], "hashes": [ - "sha256:8b7b36a949ea7f3d0504b23654040211df6f29bd04846043b464671d9c4025e5", - "sha256:b3d5c8420bbb9953af996f82f8cb28b78e02c3815f019ded094589f9854c0074" + "sha256:c21f49f5af79d320abcb61ee08524f27376df2b297d2e60ef55d9e00edd135bc", + "sha256:d7e1fceae2b1f9b214b81fdceea8d05f56f9add0f2518381cef7559bc4d5aa3f" ], + "index": "pypi", "markers": "python_version < '3.13' and python_version >= '3.8'", - "version": "==2024.0.0b4.post1" + "version": "==2024.2.1.1" }, "robotpy-cli": { "hashes": [ @@ -652,173 +291,207 @@ }, "robotpy-commands-v2": { "hashes": [ - "sha256:3b3a8b11c9f6509eeede2b37872a302228b335b3829f3436fb036323c5eb5dcd", - "sha256:dc9b49ebe42564ecace1186ee0c9f31bf7d1ad7f0fb909bf9188112d31d1e609" + "sha256:c14fad8986c94e4f1cd5eda8bbadca60b733e89d44ea1388aaa030f0de734cd4", + "sha256:f80c9caf2cce2c05f26cbe8024fc587834a07485573971bd116e3fbd6678e5ef" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==2024.2.1" + }, + "robotpy-ctre": { + "hashes": [ + "sha256:056e978d2d58aa842c69472063e21e89b0615dc6df70438ee86b4b3ea8825293", + "sha256:5d3ad9ec4ea8a7dba71979b496e9363994843e93ac4913bf80b98d9719db8d78", + "sha256:72f4c860f4e2402173a8abcdd65a6838fdd587cd2022d184fa8fd6d9645cae81", + "sha256:7e084cd2e7fc76269c3a1d4bfb671eb6c21de535698252acc879f429fa0b0ab6", + "sha256:8a7bdeb2fcebf45abc3f50b9be22b0aeef70122eda1732e37e495a530bfa87aa", + "sha256:8d44245e9159e8ccc20c239130fa15feef83ceb674a4fd0e435c91809d9ebfc4", + "sha256:92bb052508a1d65bdad5274a9bc9dc48ab001b2b65345b6e78e5689969d10678", + "sha256:ab8aac6f88b6bbfe83d42c91e52bd33d99bbb46e975c3f2a943029efcd93c9f9", + "sha256:ac3c76f65f11b4826f62815080bc7c14eaccf989790057a05980a4cca4c3d84d", + "sha256:b24aeb7f447ac7945d346247fe36db4d5cfafc0d6ec0cf294d30fd37f6bf1893", + "sha256:bd65c83ad620fc6ced2dd0111a86548ef0a0709248d40d9ca3eb524f0b366f90", + "sha256:c27f4f300df0ce2ed79bd65dff32da3b7712053572893add24a6333b89d87414", + "sha256:ec33c5a2777b15a29880a98e31de5c28f7b264afe3fccaaf983dd3853d632de6" ], - "version": "==2024.0.0b3" + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==2024.1.1" }, "robotpy-hal": { "hashes": [ - "sha256:08110bc551813c3ca633a5c9a1e7a9ad3d98f454d576e6dd0a00fec88f8b1ae1", - "sha256:1a729520e733bfa625f041c2ba54298438f1847753e27c54b9931a89a82b261c", - "sha256:1ed55be20d43afa14ee5a6904a4a2a93108933c5dcb2a497d988eb54d643d5d5", - "sha256:206204f668ac4c54d585973884719b44af356d53f0161eedde1046fe6a3672ce", - "sha256:349c30dd4ad4dc5b66436db4a0e222aaaa5afb66927fbd0d687f3fe035bcb388", - "sha256:64f8374df6ee7022e7833c64b3604eec14975dc21ff38b2fdde8734f671c4316", - "sha256:73aa5066286175d2a72232a62631ddc76608211d9b0bd092141b38a245af5a8a", - "sha256:afe42369b34a5e3d847bec0b5465327acca87506ff274d14acdd004fef71955a", - "sha256:b282855a01e19e178e51e056fb6a52066401484722bedca9d3ca954aa9adfa1a", - "sha256:b6428e16eb63eae15702724fc5c39f1da5a9c2d14abaaba9b13326ce1fdd4014", - "sha256:b91210bce47404728566f8f5141cb33fee8784eb637c16152025130584b93dce", - "sha256:c2acbfc3c401a758a4bf0d0e99353159a5ee1cec327489a4a05704b310499d80", - "sha256:e39f2f374c9873f2c268f2f4312c0f856ca56b1d8e1709d8cd689ffd42e85619", - "sha256:ec5ed002345cbc4760f2970b11fbdeeb867692546c83e1606397b48f38361528", - "sha256:f7e751ee9564a690e51c522fec3a173c1cc69bf9aed1f5fed7bcd264d818a4bb" + "sha256:03545dab1d00e8ff196934bf2f7b2f916124df75fb644690a0d01ae1fc5e54aa", + "sha256:26294b8d42259250bfdf1c093b2294aec9ec74934cf50fb94fd5f9bd77f19ac4", + "sha256:26698823ed4bbcffbb5de71e26210dfedacdcfe1a6a215cc4417b0955e006d9a", + "sha256:3964419d68b7ea80d7d4f0fce036339a2e804edc7c0b5d40a0667df85a93f73a", + "sha256:582b14e26d4f181c8481d1d9577d540a72ceacabebecbd21e7d081084cd93268", + "sha256:73fe0bd80a9651daa80351b664153b4f1322a3cb0ebf28e8b1eae32d5fb8635f", + "sha256:77c315235698fcd73f31d34e7c445fdee4b32364ac804b3cddbe6f841fcac9dc", + "sha256:9192db927dda54d383a9b9337591abb3f2c9d68a78a9da3e35bd3a8439e7d935", + "sha256:97d1ac1e640716a76ed59501631ceab3d691f25a6e2804b7b84c746052408c59", + "sha256:aa5f84f00078b91f0f9eb378e494c6e40467f262e820c2d801bc200a355a67ca", + "sha256:c5d35feadbc4ae2d94f9611ce090876bc639ef1ae0a7d8caea6f6dc569b9d2fc", + "sha256:cb4a5b7a960b32cd07dd5de8c3b59607188d467eeb8e041d29869a42cca6bb9e", + "sha256:d92d7429e41b8eb87afc9940ac8d4b45bdab327b4d364b42ec05357dd4785f36", + "sha256:da75e117675c4b59d4dc50af3147d31525e2f80fefabe52b794e7897062897d3", + "sha256:fbdff436dac6034469ba8f402ae21ace28bcf21c3bc67a571a04c131ddb0ae0e" ], "markers": "python_version >= '3.8'", - "version": "==2024.0.0b4.post1" + "version": "==2024.2.1.2" }, "robotpy-halsim-gui": { "hashes": [ - "sha256:1ae8e3b875573ba37da21a4b1fb1b09a320d3ed1f10c2c540a10b9fdf9852d57", - "sha256:564971d971fb2b67a380c0a9a004812c375a8f015da2226851ba91869766bbf1", - "sha256:618960cf8d7b33107dbd80efe4c94b9054513f022714ba32007a90691389fa72", - "sha256:6953554fc117b4b2791b7fcfc7baa679ff72675e01c55c0ba4246dcf80addf48", - "sha256:6c2a18faa35f64a3c207f148b665be044e502f54b1ebe53e12dbf2750de2258d", - "sha256:808f5f2950ea5df3a2c40f438b9f6b15b39f1bd28faef90f2216d641d4d05051", - "sha256:84a1c61596206932bae525706ed3736633f356c44bcb36edca456ebc462c1138", - "sha256:958022cf2387d89dfd7f079420c9f4e99585542935ceeb643b8abd6dd391edb1", - "sha256:a31af9cf30be74f6266f3ef2028602a318cacdd9077e6e486b2e29ae5454cc73", - "sha256:adc7df56c7a52597aec5fcff7314f5ec27bac8c9bf5c2132a4e8eba59b889894", - "sha256:bb0cde93f1722287448f687029dd0271d84e6af56b7e24a5c2c2d711946aacbd", - "sha256:c07b55cb82472ccea87c52dd870b965d4c178a0b1e5cdb1ffe169f361f37e9fc", - "sha256:d537bd5434b7aeaa615347615854c85d85327bbca0a18b341bb4288a91e5e3fe", - "sha256:db07331200ff631fd448432d196f83e2160a0378693ea2713381393f766d2956", - "sha256:dc01c9144589c5eae149102e94bed0af67d73765fa21866f7d29852e12306e82" + "sha256:0a276bbaaf523604397cbab492d347a2e9733675a773bfec1faf93e8629369ed", + "sha256:0fe53bee95335b73ff25a2dff5f25ff324111e7023118dfe2b2aee38017f6c9b", + "sha256:12b7c2803cd7f9f746dc1a383c3ec8a675cd61a92fa3d320cde5467115871d39", + "sha256:18c9c03cf4c84a1e0a6e18dcd01a5ddaa684b3a65c614a930ed85185ef1c113f", + "sha256:1a4e9d3f428a1b22c3d7a146703fee844c2fe9dd3a6eabba345a26d64bd7e1d9", + "sha256:27f024c5a035a1f4929a427a5554c1dce45facc44a9180e0b76203de0a360511", + "sha256:3756d5546f5daf8712bd5ae4cc080ae807e71b599fd7de5c3e2d13285b3031b2", + "sha256:4563d2b0d58c7c2d179647c496e8f6b5665308fddd3b584e26c7005000707169", + "sha256:473ad062590d5969c07a79d1449ceddeec14635c9055330a698b7944bc4565eb", + "sha256:64940e45d0b79b0a08ecc878245d2a676b48b8b34e39801773e9622abefac03f", + "sha256:7afc42055722b40764f16838d981ec92ac37de5c719ab12cf6c5c9278e7c2a2d", + "sha256:902877dc1963be58399a586916cfad76ca8439cb44cbf94e6d50b0bf9133a55d", + "sha256:91ab958a9e4310a6d900d4dc55dd9681939631d8585a1071e5bdedc22b9a66f0", + "sha256:b3b05bfa38c65fa072043abbf7135851c0167ab1e25abedecf61160bf9a0d598", + "sha256:fae0127e462215e1de12c252561c56641f6dadbafccf7b21f1cc29a67e53574e" ], "markers": "platform_machine != 'roborio' and platform_machine != 'armv7l' and platform_machine != 'aarch64'", - "version": "==2024.0.0b4.post1" + "version": "==2024.2.1.2" }, "robotpy-installer": { "hashes": [ - "sha256:302987a3e64580dae0f2e21969aa61fa2f59114c077d2fe011629f641dee514b", - "sha256:9b93cfba473716c6b899d8f5c550ba64f52ae328f393fb00df3b086762b34142" + "sha256:0ab8a074fa4c342e300f3f942fd738b8a6a45df888f5e369868d306d8fe9a541", + "sha256:917d42d1e2a098caa61d00e8f1801378c354edf605b4d0c95373272096f91195" ], "markers": "platform_machine != 'roborio' and platform_machine != 'armv7l' and platform_machine != 'aarch64'", - "version": "==2024.0.2" + "version": "==2024.1.3" }, "robotpy-navx": { "hashes": [ - "sha256:0469270c0993dc77538febcb3731e322ba5a521fa6a2793fc5f3dab1e51e641e", - "sha256:110daa49b0040de731a782b57fe9859c2aee5f017b2afa9cb8d4a0a8a2353c1a", - "sha256:16273616bf6d377576977c309c74a8d81fd9dd0b98cd08ad24e402734e892803", - "sha256:16c8c87989f3b181732a6d6e7de9337741b24154368ad78ac0988fbfbf57a96b", - "sha256:1c3aca092d5db8a70b92686eebebf9ae51ca198f8a008d74dd3399326c03c6ef", - "sha256:42d0c8c112be90fc7d22a64c1d8e05403db74a9f361de7c2ddbfecc82cb414b3", - "sha256:5471062a04e3b308e68deb251d65306f49dda5811a709b451930fce2e8025be3", - "sha256:5a26764370cb166525e254dd3ca7380159fddc9d66e9af8218ad08a9b14d7e28", - "sha256:692b2bd39267f30b7a34ad40f953c7dc88b672279461a047801c51eadd1aae24", - "sha256:7c5a47b0eaa77ef40c756e5ccf5d59a2508eea477b7fc2e6726d2019acd15b87", - "sha256:8df9d51e5f53c4d757c0cbdbcdfeebb748abcfba25521a1ed1f47d3d4185f9ed", - "sha256:99340dca9323d95ee85f0a15a2eb352a813e219779bc3b163c867f354d278c53", - "sha256:9d3bb477d7de09afeb1f897563bdb7fd4ee0cf3598fafeccedc58c673b4d4b16", - "sha256:af4816150085738dd1b18f556842a2941a024f3907b485776449f0751e0e8e90", - "sha256:d2d3e2855aa163d395cb30edb8ec402916af6034cc4bae8d8c9c7562092103b9", - "sha256:ed44e2ad59890522e5fd38ad1a724ee0f7b2a3a802b1ab583ff25737b700fb84" + "sha256:00282c61864bfcbd104cbe2ee10b0bcfb517adb27586f43cc89a631c9d471189", + "sha256:004b6b3a88cafda02b7258203687d844c91f921d2c204dd8838390f17a5febed", + "sha256:0c3e382fe21196d3eeaa906d9e82b18711af7690d159cb7af999b8a733d39ebb", + "sha256:1e24ba17aa30bd926569cd3def6ae1c96b64ba1a02a7c87a42c51b16d82a613a", + "sha256:383e7cdc303934932fabfe33a7fae536d8dbc133d7135a08fc26f821592cdbfd", + "sha256:44bbf7bbfaa26ecf59a8a361842f5e89bb7ab44116e4b6a82675d98813c7e045", + "sha256:5c7e5edf7c51d9e9280215cd182a3c71d65fafdf1a1f9e2ef6c98cbd2bb0ff9a", + "sha256:5e5b7389dac357825c76fe69e09475d00477c2a1de2b6b6b7ef00f4461e6cf06", + "sha256:6e2fc4c871a20d305fb9f6ba5cb5cb424f9a31b78327b77c3f7e28c2437f84d8", + "sha256:816d52d172ff1bfc87f10a91fbbeb36f873f6e02a1c16fb3befdcad73cf266f2", + "sha256:82598483738393ad7e94fb3ad73628c2ee842329ef526e1b52a05b7945ca10f4", + "sha256:a56f6c71678b23cd3f9ce376d7040243b921c01dda8d0de8a828b4a2db45d6e2", + "sha256:a6757655b2aaa1d8028068f22b4c0fbddcb38d3189f9efcaa6f97204d70d2632", + "sha256:ba22ed1be09525ebb35e9a5ee1a4eca7953848a8b0fec167398e167db9490025", + "sha256:d896a66171b18f47d7d47c4516a00c47da77cc7e68f91c182dfa38adb61fdc64", + "sha256:ebc481d6d8b3921d7fb58a9d7820fd7ccc94d1aac2fe189ac35dfcc38c6bfa91" ], - "version": "==2024.0.0b4" + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==2024.1.0" }, "robotpy-rev": { "hashes": [ - "sha256:0b6374e89d7da292af112b0580205f420250374f635ab3b2468033f8d6c155a6", - "sha256:0c19c45075ce199d4480d390dbfdb3dd399af250cc7abcc3815c83ce657944af", - "sha256:0e9b8a267909746fde21002736564eeeee5ee5259b7d1d1db4db4e9c4225fd82", - "sha256:0fa19d2a919ccda8115f395c7d63f1eff184ef268397bf4123b8eeb90b0ba9a6", - "sha256:151b16d2f818a20875a76141cb45c19ef8023e2c14b814a6ce6aaf771dac44dd", - "sha256:1e9bf067572df49bc31a3891e942b57fb5b9a721c97795d057f6adaeb1088345", - "sha256:30ffcd5b58726dc95b974299a20907f593d807cda75bf03c9d51efa1dfbff37c", - "sha256:3a020faf21f3c58e0693c8f2149496d548d52247939878395bc16f106eae437f", - "sha256:5158cf70a18a715e2713b036a3593504b03cd195d36cff08393760e754f56e1e", - "sha256:561e5438d4f93e388729fa733d68ef78750079455cb3dbbba7e33751ec90cf5b", - "sha256:56866ce655966ca4caf05845cf97db2fc8609409a43436631791cc1f5efeb9e8", - "sha256:941dd2a6081f9eae5feaff82144ae5b441634040fe99b414a6295d6300d7cd62", - "sha256:9db89303a5b0fb64414bf19fb664972c6396c344768ba81e3294578657812626", - "sha256:c7b542ff2f7918b628ab7a23542ca915261553b0d94d8e942be6d16c07b4ba7a", - "sha256:daf5cbc0281a53a662f5e12ac89947cf9aff4f1612661450f0467b930c4f3f9a", - "sha256:dbd208af3037ee58628a40f98ff265a8c9c83617e354bbfc942d947a30c33660" + "sha256:15cc9e8e7bccbea8f508c53f8fe40dafb539b1b07b54f45f13445b370fcb73a9", + "sha256:1a6126ae57485eaa3f57657e81e021e8f762388a167ddf9bca520a527bf880cd", + "sha256:331bb9e17b18d844a940a9b1944fd335f739d9885c51de3ed2895c34c2200c1d", + "sha256:3df12e1c5d9df3a4492abfc8d192006182d4356b687708edf214e1b683911017", + "sha256:48634ff5bb8cf0fc9233fa8f69fb2387d08d59758f9536d762bb8e7374351834", + "sha256:4f981f40cb848cbffa1d678fdaa8d05ebd1c727bc0572142626714c79ba6bcd9", + "sha256:59ae89a3450444fbca48beeb9abc1cadd39452f1fb9a059f06d41c7bb8b24af6", + "sha256:644592718825d8029a0b506986cdcbaa8abfeff59f750305c0ca91849a6a38eb", + "sha256:8673fbc3ceb5f69674560f1877128429d3365bf1e61594b70d593322ca455960", + "sha256:a62b32f743ef9e27c54443819544e31cdaaccbf24db07c4766d055958864b409", + "sha256:bcb2679eaeb73a90e83694192e64fa8c3a87856ec42edfc16ffa0f718fb2400f", + "sha256:c4698be1c7df04ebb7d37cf80c94d6e4c626ab0a55d64c66556085b0b4bf994a", + "sha256:d021d19d2116279aa912edd93b6864fc36c624aa138f0a54a628df210ff97a0f", + "sha256:d5bff680765dadb2685a29640804259bfa3794a7b918d9242b6c27895e6e8417", + "sha256:dfcd8c4497e09cb83d9370ddb98c5ae9683b3a9d90b8e5de126a490061244ceb", + "sha256:ffd8748e1425f674c1fb0fe51620f7da9f40c11a7643f9c03139747e7237aea0" ], - "version": "==2024.0.0b1.post1" + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==2024.2.0" }, "robotpy-wpilib-utilities": { "hashes": [ - "sha256:2245f6ddcfe637151938cf55b6ac1b5617c60b683834aaaf4627e1e721261243", - "sha256:9b7934154765c7acc34937be09aca2216b6aa88f086fe1ca8d2e8250fe4be70e" + "sha256:da0d3495d28b8f758c0bc12f1075996273aae831c5dd9d85d6b0581f8f08bcaa", + "sha256:f2e7e512e3e9ad938893175b22c827f97d0866ade47f34c25d68622c3f8a4c3a" ], - "markers": "python_version >= '3.7'", - "version": "==2024.0.0b1" + "markers": "python_version >= '3.8'", + "version": "==2024.0.0" }, "robotpy-wpimath": { "hashes": [ - "sha256:16a929e2c65e69e5005aaac8b4a2b8e261af3210b05742921527b5eafb77fef0", - "sha256:1cdaf001ecd043e46c7a33e6f733e4bfbda6d3a6a38365fd8b060dda43df7dee", - "sha256:2e75b63692cfc9d4c35a2394ed10339867092474ab90ba6d6f6961633c8f424d", - "sha256:5099ea19f0de6a62386791d537f668baedd655e81002b13798eb41ee7e2f52db", - "sha256:54d8c724f1036588751d78c645a3a3c7350149901c45c3525daf2f25eb0431d3", - "sha256:5538834eeaa57203122be6ed493b00f28d264f313eedca8e9123b05487fc8ab5", - "sha256:61f6d69b968b3e449bcee51d2107b62c907592f7d9f2f857822e97d57e25366c", - "sha256:6375ead959905c8fe000d8f435152cbea590f7cdee3a787dacd84b18d02ccd19", - "sha256:7024df4a528d82011d5cdd00a6e899a1d8216bcf18aa05dbd0cb5ca459af0d9c", - "sha256:76a77b8c9971b1d2078fafdd4572fa1daabc053b9d2324b21bd5a92856cb8b2d", - "sha256:8740ea96fe07bd9ddc64f125898cf5b02f853c666964460f9b72aff7bbd110ad", - "sha256:89a81a2f12a3708d7344017ed888953b53158faf5b46ca2ec65d9c8515cbf1c8", - "sha256:9af91189df840f90220c6418852cf0f9334b1ed78efc5d4556a8b8b5b6d58f2f", - "sha256:f04164d04da8a3bce4ccc8dd203abd0f5e30d381e70467d1366203ee7db466ed", - "sha256:fa949dce76b7a4ff41918099db6a4615bc2690a2aa1ad1f7e69b631cdc8c9e82" + "sha256:00a4b8dc79656050f81748efaa462dff04948bb71916c185d3fa188487113fdc", + "sha256:07b2172efc025c52f958c80115a4043892d10bc0db22dbaa871b32dff5a2f745", + "sha256:1a1c7c7fe30f1af433df3b47d093a5d2d19f57ec1fcd343ff1762d28d2416857", + "sha256:32a0ab62c5e1eca977b9c7b894faec18feaeca791f4c2f3bd6815ff6663a95a0", + "sha256:4a0e00af2a5a25ec641b036389ba1a8ce3ee6d023fcec3f994ee5788478f74f5", + "sha256:4acca2fb7122f23829458a08de31d60dd68de9cf4c18acb64b94f97adb1332f4", + "sha256:4bc7205fa4d41ccb2b53ff33dac013370fc040fe7d6a1253fd7f417c60e27409", + "sha256:562da0476906b745585d34f036edfc49ec95f0d08266520e592051c34cdb1e77", + "sha256:6cb06f8af879ad7959cb4a53ed4004688a7a0845729ddad1457781aee8e827ca", + "sha256:8f9ce5c6507c31ba5091e74c17f8edd48113428c7b08f67a3a8f355ce6fde488", + "sha256:ab0b61d25c97fe277c29ffd8e41b9b377ed691e5b1079bc5bcadd75b003d7c98", + "sha256:bb7898148442690572e5a94dcceed085048d8d0b18d1f67b91cb9f54615e8aef", + "sha256:c5c431c9fdd9f354f20a3a97711ca9d1f3cf75561a3baa6d102c7c68a6d4873a", + "sha256:d7212560be85935b06fcab798fe9d27f6950f8064f70999f1b4e056a17328f8f", + "sha256:f8e2d84acd255431c4346d7f07fcfd638da46aadd32872483de15aa11d34f520" ], "markers": "python_version >= '3.8'", - "version": "==2024.0.0b4.post1" + "version": "==2024.2.1.2" }, "robotpy-wpinet": { "hashes": [ - "sha256:01ae24a095ec1ed28cc37e2f539f230dc4f3ee3794acc8a2a82d57140d1791ef", - "sha256:0da284c024681a6d3a94012ecb2f3a5861a970a74410c0a933fc70069c029a76", - "sha256:1b1692e1e32e6568685df0ae02a5774b36dfedf22c6379d29c040473f023fd68", - "sha256:1fb553501aa084c6b141d38524d1b0b38c92212006c39f53a25ddbbce68cba50", - "sha256:2e9f1dc938cd993756b7498bcbb61b8fb197f61bf1fe67e3339935f512d9c17b", - "sha256:44c2e8b4a216a5b1b3ea729b51b251e02a7e0b5c11fb6a7dea0bd5a305c1e348", - "sha256:5a01ef456f13f0bf088e1a97917fc0f8fa15562d118ef3f9681cc31d197e2807", - "sha256:5bae69d897b5697b102c33295a601caba1886af06b2394224fe69f1ec4e423bf", - "sha256:6469928546dce75177d320b093e3fd45658b503ccd4833e2260d67d01aceeb60", - "sha256:99908fdae80d524f2e1651615821215ea612824bafa340162587ea27c29d7c01", - "sha256:9c6bc1717533a84a50ef33ab50db99ccf0f53cea358af635ad1f33c985217944", - "sha256:a36403023c2e2530c9913b85e6bf0d90a9f94afdb5e10b2e67361ae115982800", - "sha256:c0497817c4aa0aa12e0e207855fc06b38cbffa57b8f85d95374c35a009d31b80", - "sha256:df6bb721de86c9c1ba75ba892adb7f6ac31211e4da937178a81e7219d2f91954", - "sha256:e8b1394b4258352ef1e73adc2761d402bf88d553cca16098d1cb323e9f9f8b84" + "sha256:02b279d069ba20e0e4eda90bc6e116eb10d89df0370067ca7d9649ef9b2efeb9", + "sha256:02cebe13d76064044c106cd1e8ee9b18e63e6b8371c6041326e5730dcd9f5b03", + "sha256:1a8ed49cdbd748c0dbe15e993ebf26f18d49f400d8efb823b5272c61588988c8", + "sha256:4aa2c2964654262c944226a92a5095d260677d4da287beca2e5353daba225ca0", + "sha256:4fddc51d455591f4657205740df068a42040885e576c719b7a19b9c4fb5e5b55", + "sha256:5cc7838ea6b3b7c7d021c080c19e3bfebb23f52e00928916e4fb46fcf8c3ec64", + "sha256:96463e262e7498a42dc51add5d7fde71da875f2aa314a3033bf956eecb5ad289", + "sha256:ba0276cede651001e963ac98ae57731e1cd2f915e7fd77e04ddc623a55747d5a", + "sha256:cbd64df8095864b933c73344180d8dc2079fa290f93e10e6c2e894ae1eafcd5d", + "sha256:cd136c56e72a2a652f5ec904bd04634c53ac7946d52bb7412cb2f1f0a89243b2", + "sha256:dd267e2415201e10b2b5c5c0de7b2277b111794d8c2c94420af66c5dbe36b958", + "sha256:e14ad187c3ddcd68e0dedae6f5f7ad1831e98c68b48e6745cff2620f018a656c", + "sha256:ee716c89d34df41d3e6532bd92975ff68fddbaf91a7f4feb9e2f9ce9dcf3997c", + "sha256:eebe52fb5cf4bd63210c9cacae0b2b532d505e993df1666cf1283c0e736594f8", + "sha256:f956c46b4d0917ce881e620952b125676537e3347fc486b05882731369b38b7d" ], "markers": "python_version >= '3.8'", - "version": "==2024.0.0b4.post1" + "version": "==2024.2.1.2" }, "robotpy-wpiutil": { "hashes": [ - "sha256:0399d34dfed60be04ebee1fa3eac1e648b1d5474dcaaa16ba1051c086b3229d2", - "sha256:04fe774d0e22a30080cd5616c6f3b146ff51c13f5bc429b5df3f42ea6e135a5c", - "sha256:1491121b000fbc8736be8a32862b30e393c05a0909e574236a7f911c9dc8ae96", - "sha256:1f037175da00dce6442381377160131c2935a75b2bf710cfdbca6a4f739b9d7e", - "sha256:23dc3107d761808d274a0e342fa7b96e4be5c94b97465de5751ac0121d6ba532", - "sha256:3f110b3c0444a6c867452272718916769e818f3acb9ff62976783fd671b7e915", - "sha256:483131793247d6fe9eda9a2fcc72cd273fa9aa18738a3becad2d3bd757a975fb", - "sha256:602f6bb8e181da649382f77b6e625249daa6f66efb21ce463ed612c8e81a3ab4", - "sha256:76f96b4b0f0feb0f72fcf9314220c9edcf362e4c3da94b15cf21bc27d5b406e3", - "sha256:87e7dfd483943d8c454e874a0fc0630c517f078c7c918630847e1cc3a3f09507", - "sha256:aeb00762e5350587ee1bad2e35e4a23c5685f4b821a19e50f4ff5ea9664175b3", - "sha256:c236ee7ae362d488d193cc443ccfe5956534ce98e72564bbde55012972a821fe", - "sha256:db5dbe0fba1ad09aa42575dab59d334f2637a60ee4f3035303bd9243cfca47fa", - "sha256:e998f8fe7b502fb06cb2000fb485cecb863469af2b3cf05a4766cf040bc79c75", - "sha256:f4b7a448739c8d8045a297406c402da65033a14b4cc79fef2d1cca938d1802cf" + "sha256:5ba7e3df22812e7924cfa2a868dc76fb4a06077d7ea32f02e662db5ec92fd1b8", + "sha256:6b0b4e3f6a0a354d64d600d87d1e06c4ed9aadbb16d69b3eb280723fa781e31c", + "sha256:6e3b410661d69d02d14929e9dde6d4272a334606ada546331a0e5e087cbcc037", + "sha256:885aee82ab121acc87167e795d4e7217ef40521ac3d993dc723faef2b26e0d04", + "sha256:95a1f0eb1dbad058937f4baa2c2942b6344f5a523a0784a907c750c482caf407", + "sha256:9a90190ba1b8b3b7eb76f0f5f0c40b0a18256e7ecf2ebabccae615389ebb9575", + "sha256:b1a005bb75160aa40825b3d436dfa35b606db674f143b61d77af7f7680308f02", + "sha256:be6ead686096ee25dbe096f1ca1bee1e7db9d42739144bc1eb7af327a617e658", + "sha256:c50f7384224753e2eeae188610bbcf58604275b66efbd189f4dd94ed9b5c244a", + "sha256:e621b62bf4320cb68d270fe12b7f78b5dfac56c1d54703d5822e7dac6fd23d70", + "sha256:ebd3c8fc4280172adf34346a2302ec985f0d8730f3f95200a66c3f6da83613c0", + "sha256:f0029684f096d2ba1618aebffbc126dd571aa2a0d3e73b0c2b3f016e6ec996bb", + "sha256:f69a8b2e2c7a626ab3fed8e5ca3dc017e2871226ef03ec045e4cd7da658d873d", + "sha256:f8c44c5fb1300299d65a89bbb7162465a8201a64175ff06f35768b6ed1c4e4f0", + "sha256:fdee662f432ccd717366da9ea3b5e152e84ee74e6a4c2a95d4c251ff82736fcf" ], "markers": "python_version >= '3.8'", - "version": "==2024.0.0b4.post1" + "version": "==2024.2.1.2" + }, + "setuptools": { + "hashes": [ + "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05", + "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78" + ], + "markers": "python_version >= '3.8'", + "version": "==69.0.3" }, "tomli": { "hashes": [ @@ -841,555 +514,25 @@ "all" ], "hashes": [ - "sha256:21f4c8b5d295ead0c4b52a82fcc42077ebc201438eee0cb8fa713831526711af", - "sha256:3c36adff768e246220bccf56db8bdcac4f635f9f0e63b911c41084d6787eae3d", - "sha256:3f374998ac9175ac515b36387c909a53c95d54cd279124e955e7c1ac2d3535f3", - "sha256:4976ca4fba98e28e091c1692dd6a5882ff4d7b6d31433832398a84f66b38aa3d", - "sha256:5d1e837e8fe506b5741915396fc171808ce9444cd9ed01001bfb7c0781a38e50", - "sha256:7e21e0af9079ffc8af388dc44bea6a02c740601f21b0fbc5a50e9c57e2e7b1a8", - "sha256:8e03e37df98c5a40c08bea4f8b67da78428256c5d739c8385da7a006026b5623", - "sha256:9dd896250c8a1e88b9da48fd5a881f9cac9f1bc684f0f9a32c5e883c2e156447", - "sha256:c126145c3b3c42fb72c54835a78c7078324ee72ab53c2a4cb188763731bf7c7e", - "sha256:d0f090f087b817aa518ce6b5209f3c9159c9cd7394c2d6dff3132fa7e6cb26df", - "sha256:d35dd7c89529c2b1badee4e017aeba20eb294c87878b5c2be89365df330a7fa5", - "sha256:e8ef1bce16b2601daf123fc6226ee915c31952408442f976243255a98cf62f80", - "sha256:ec674d6e0bfe972aa84dde896c9fa3168d1d18c77d9091060b4f9d2c1f601111", - "sha256:f1a04fc08157b81e6115824790f508a8f32f4d8e4f50c89a54d9346ca9af0eb1", - "sha256:f381dc85c1c7787e89730059a4e33172268d7efa699f2e8f9b0ca72733b38303" + "sha256:0829435a16cda9f312962afe7f63dcf5812215048f29cad3ec8cfaaf66ba9d6e", + "sha256:0b9a102c2fe1e7322c6c2ae4c249aa61706bce84f13168ed8d35d0209e62394f", + "sha256:1f280c68acc2a83b587ffa3d3dbbd731f842b318d6a207d5b2a03ce17f781168", + "sha256:24b58eea56909cf6de0ccd8320dff02b0c47c33c2c761c518c918582b5cf8ac8", + "sha256:41f439f2389437547d39124a2a4780877603a220a3eb7b03a521b18dcbe8e637", + "sha256:5690544babc6ccbc5785b53f8d5aed2db6fdbb68f5e0b01d7d85cd112af34fba", + "sha256:57c7d72d9326b6cee51005fa13926b907c4e37851da5727fc086b0e5b8972c5b", + "sha256:5a93a4634babbcc111adc8edd5c309cd4654f6fe4d271cbd67fd250f9a8b6bbb", + "sha256:93acc9a77fc78fd9b6c8a7d048ff60024e930abb6671c3a29c0cdc774198d7b5", + "sha256:95ef8391edcee26f29081705664b7d59c4c51c34c92047d6aa28af5345dd2b11", + "sha256:ac186f81c3c2246cb9ce4d83f5c87cf496e47c4eb0b6096f2a53f0d1d5399ac4", + "sha256:afe472774b69e65b7dc99dbfd42e3adafb7156b332122b1e5eba660b05d7f383", + "sha256:b499bb809b24208f50b83fb79e452dacc28701bce964fae35a41085efff4a39f", + "sha256:c9fdd5d8377fbe990af506b304b7efb24dd1888ac1d18ab85f5ea84f1da2bfae", + "sha256:e644e7f6c0b4d1fc71c1cd8efebf908ab4088447db939ee213286703990ca860" ], "markers": "python_version >= '3.8'", - "version": "==2024.0.0b4.post1" - }, - "yarl": { - "hashes": [ - "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51", - "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce", - "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559", - "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0", - "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81", - "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc", - "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4", - "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c", - "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130", - "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136", - "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e", - "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec", - "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7", - "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1", - "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455", - "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099", - "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129", - "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10", - "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142", - "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98", - "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa", - "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7", - "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525", - "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c", - "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9", - "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c", - "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8", - "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b", - "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf", - "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23", - "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd", - "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27", - "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f", - "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece", - "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434", - "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec", - "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff", - "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78", - "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d", - "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863", - "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53", - "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31", - "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15", - "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5", - "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b", - "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57", - "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3", - "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1", - "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f", - "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad", - "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c", - "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7", - "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2", - "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b", - "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2", - "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b", - "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9", - "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be", - "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e", - "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984", - "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4", - "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074", - "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2", - "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392", - "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91", - "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541", - "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf", - "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572", - "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66", - "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575", - "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14", - "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5", - "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1", - "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e", - "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551", - "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17", - "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead", - "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0", - "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe", - "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234", - "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0", - "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7", - "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34", - "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42", - "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385", - "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78", - "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be", - "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958", - "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749", - "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec" - ], - "markers": "python_version >= '3.7'", - "version": "==1.9.4" + "version": "==2024.2.1.2" } }, - "develop": { - "aiohttp": { - "hashes": [ - "sha256:02ab6006ec3c3463b528374c4cdce86434e7b89ad355e7bf29e2f16b46c7dd6f", - "sha256:04fa38875e53eb7e354ece1607b1d2fdee2d175ea4e4d745f6ec9f751fe20c7c", - "sha256:0b0a6a36ed7e164c6df1e18ee47afbd1990ce47cb428739d6c99aaabfaf1b3af", - "sha256:0d406b01a9f5a7e232d1b0d161b40c05275ffbcbd772dc18c1d5a570961a1ca4", - "sha256:0e49b08eafa4f5707ecfb321ab9592717a319e37938e301d462f79b4e860c32a", - "sha256:0e7ba7ff228c0d9a2cd66194e90f2bca6e0abca810b786901a569c0de082f489", - "sha256:11cb254e397a82efb1805d12561e80124928e04e9c4483587ce7390b3866d213", - "sha256:11ff168d752cb41e8492817e10fb4f85828f6a0142b9726a30c27c35a1835f01", - "sha256:176df045597e674fa950bf5ae536be85699e04cea68fa3a616cf75e413737eb5", - "sha256:219a16763dc0294842188ac8a12262b5671817042b35d45e44fd0a697d8c8361", - "sha256:22698f01ff5653fe66d16ffb7658f582a0ac084d7da1323e39fd9eab326a1f26", - "sha256:237533179d9747080bcaad4d02083ce295c0d2eab3e9e8ce103411a4312991a0", - "sha256:289ba9ae8e88d0ba16062ecf02dd730b34186ea3b1e7489046fc338bdc3361c4", - "sha256:2c59e0076ea31c08553e868cec02d22191c086f00b44610f8ab7363a11a5d9d8", - "sha256:2c9376e2b09895c8ca8b95362283365eb5c03bdc8428ade80a864160605715f1", - "sha256:3135713c5562731ee18f58d3ad1bf41e1d8883eb68b363f2ffde5b2ea4b84cc7", - "sha256:3b9c7426923bb7bd66d409da46c41e3fb40f5caf679da624439b9eba92043fa6", - "sha256:3c0266cd6f005e99f3f51e583012de2778e65af6b73860038b968a0a8888487a", - "sha256:41473de252e1797c2d2293804e389a6d6986ef37cbb4a25208de537ae32141dd", - "sha256:4831df72b053b1eed31eb00a2e1aff6896fb4485301d4ccb208cac264b648db4", - "sha256:49f0c1b3c2842556e5de35f122fc0f0b721334ceb6e78c3719693364d4af8499", - "sha256:4b4c452d0190c5a820d3f5c0f3cd8a28ace48c54053e24da9d6041bf81113183", - "sha256:4ee8caa925aebc1e64e98432d78ea8de67b2272252b0a931d2ac3bd876ad5544", - "sha256:500f1c59906cd142d452074f3811614be04819a38ae2b3239a48b82649c08821", - "sha256:5216b6082c624b55cfe79af5d538e499cd5f5b976820eac31951fb4325974501", - "sha256:54311eb54f3a0c45efb9ed0d0a8f43d1bc6060d773f6973efd90037a51cd0a3f", - "sha256:54631fb69a6e44b2ba522f7c22a6fb2667a02fd97d636048478db2fd8c4e98fe", - "sha256:565760d6812b8d78d416c3c7cfdf5362fbe0d0d25b82fed75d0d29e18d7fc30f", - "sha256:598db66eaf2e04aa0c8900a63b0101fdc5e6b8a7ddd805c56d86efb54eb66672", - "sha256:5c4fa235d534b3547184831c624c0b7c1e262cd1de847d95085ec94c16fddcd5", - "sha256:69985d50a2b6f709412d944ffb2e97d0be154ea90600b7a921f95a87d6f108a2", - "sha256:69da0f3ed3496808e8cbc5123a866c41c12c15baaaead96d256477edf168eb57", - "sha256:6c93b7c2e52061f0925c3382d5cb8980e40f91c989563d3d32ca280069fd6a87", - "sha256:70907533db712f7aa791effb38efa96f044ce3d4e850e2d7691abd759f4f0ae0", - "sha256:81b77f868814346662c96ab36b875d7814ebf82340d3284a31681085c051320f", - "sha256:82eefaf1a996060602f3cc1112d93ba8b201dbf5d8fd9611227de2003dddb3b7", - "sha256:85c3e3c9cb1d480e0b9a64c658cd66b3cfb8e721636ab8b0e746e2d79a7a9eed", - "sha256:8a22a34bc594d9d24621091d1b91511001a7eea91d6652ea495ce06e27381f70", - "sha256:8cef8710fb849d97c533f259103f09bac167a008d7131d7b2b0e3a33269185c0", - "sha256:8d44e7bf06b0c0a70a20f9100af9fcfd7f6d9d3913e37754c12d424179b4e48f", - "sha256:8d7f98fde213f74561be1d6d3fa353656197f75d4edfbb3d94c9eb9b0fc47f5d", - "sha256:8d8e4450e7fe24d86e86b23cc209e0023177b6d59502e33807b732d2deb6975f", - "sha256:8fc49a87ac269d4529da45871e2ffb6874e87779c3d0e2ccd813c0899221239d", - "sha256:90ec72d231169b4b8d6085be13023ece8fa9b1bb495e4398d847e25218e0f431", - "sha256:91c742ca59045dce7ba76cab6e223e41d2c70d79e82c284a96411f8645e2afff", - "sha256:9b05d33ff8e6b269e30a7957bd3244ffbce2a7a35a81b81c382629b80af1a8bf", - "sha256:9b05d5cbe9dafcdc733262c3a99ccf63d2f7ce02543620d2bd8db4d4f7a22f83", - "sha256:9c5857612c9813796960c00767645cb5da815af16dafb32d70c72a8390bbf690", - "sha256:a34086c5cc285be878622e0a6ab897a986a6e8bf5b67ecb377015f06ed316587", - "sha256:ab221850108a4a063c5b8a70f00dd7a1975e5a1713f87f4ab26a46e5feac5a0e", - "sha256:b796b44111f0cab6bbf66214186e44734b5baab949cb5fb56154142a92989aeb", - "sha256:b8c3a67eb87394386847d188996920f33b01b32155f0a94f36ca0e0c635bf3e3", - "sha256:bcb6532b9814ea7c5a6a3299747c49de30e84472fa72821b07f5a9818bce0f66", - "sha256:bcc0ea8d5b74a41b621ad4a13d96c36079c81628ccc0b30cfb1603e3dfa3a014", - "sha256:bea94403a21eb94c93386d559bce297381609153e418a3ffc7d6bf772f59cc35", - "sha256:bff7e2811814fa2271be95ab6e84c9436d027a0e59665de60edf44e529a42c1f", - "sha256:c72444d17777865734aa1a4d167794c34b63e5883abb90356a0364a28904e6c0", - "sha256:c7b5d5d64e2a14e35a9240b33b89389e0035e6de8dbb7ffa50d10d8b65c57449", - "sha256:c7e939f1ae428a86e4abbb9a7c4732bf4706048818dfd979e5e2839ce0159f23", - "sha256:c88a15f272a0ad3d7773cf3a37cc7b7d077cbfc8e331675cf1346e849d97a4e5", - "sha256:c9110c06eaaac7e1f5562caf481f18ccf8f6fdf4c3323feab28a93d34cc646bd", - "sha256:ca7ca5abfbfe8d39e653870fbe8d7710be7a857f8a8386fc9de1aae2e02ce7e4", - "sha256:cae4c0c2ca800c793cae07ef3d40794625471040a87e1ba392039639ad61ab5b", - "sha256:cdefe289681507187e375a5064c7599f52c40343a8701761c802c1853a504558", - "sha256:cf2a0ac0615842b849f40c4d7f304986a242f1e68286dbf3bd7a835e4f83acfd", - "sha256:cfeadf42840c1e870dc2042a232a8748e75a36b52d78968cda6736de55582766", - "sha256:d737e69d193dac7296365a6dcb73bbbf53bb760ab25a3727716bbd42022e8d7a", - "sha256:d7481f581251bb5558ba9f635db70908819caa221fc79ee52a7f58392778c636", - "sha256:df9cf74b9bc03d586fc53ba470828d7b77ce51b0582d1d0b5b2fb673c0baa32d", - "sha256:e1f80197f8b0b846a8d5cf7b7ec6084493950d0882cc5537fb7b96a69e3c8590", - "sha256:ecca113f19d5e74048c001934045a2b9368d77b0b17691d905af18bd1c21275e", - "sha256:ee2527134f95e106cc1653e9ac78846f3a2ec1004cf20ef4e02038035a74544d", - "sha256:f27fdaadce22f2ef950fc10dcdf8048407c3b42b73779e48a4e76b3c35bca26c", - "sha256:f694dc8a6a3112059258a725a4ebe9acac5fe62f11c77ac4dcf896edfa78ca28", - "sha256:f800164276eec54e0af5c99feb9494c295118fc10a11b997bbb1348ba1a52065", - "sha256:ffcd828e37dc219a72c9012ec44ad2e7e3066bec6ff3aaa19e7d435dbf4032ca" - ], - "version": "==3.9.1" - }, - "aiosignal": { - "hashes": [ - "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc", - "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17" - ], - "markers": "python_version >= '3.7'", - "version": "==1.3.1" - }, - "attrs": { - "hashes": [ - "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30", - "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1" - ], - "markers": "python_version >= '3.7'", - "version": "==23.2.0" - }, - "black": { - "hashes": [ - "sha256:2220c470c22476ca9631337b0daae41be2b215599919b19d576a956ad38aca69", - "sha256:2a12829e372563ffff10c18c7aff1ef274da6afbc7bc8ccdb5fcc8ff84cab43f", - "sha256:3d139b9531e6bb6d129497a46475535d8289dddc861a5b980f908c36597b9817", - "sha256:41c0ce5cbdb701900c166bcca08ac941b64cf1d6967509e3caeab126da0ae0d0", - "sha256:4a159ae57f239f3f1ef6a78784b00c1c617c7bb188cc351b3017b9e0702df11c", - "sha256:4de8ba5825588017f90e63d7a25fc4df33a6342d1f4d628ad76130d8f4488fc6", - "sha256:623efdb54e7290ba75f7b822dfd2d8a47a55e721ae63aab671ccfd46b2ba6c5d", - "sha256:6b594b3ede60182215d258c76de2de64712d2e8424442ff4402276e22684abbe", - "sha256:6e3c74b35ea179bb69440286b81c309a64c34a032746a9eef3399dc3ce671352", - "sha256:87c8165fad00b03d9c1d400b1dd250479792f49d012807ee45162d323d04fc06", - "sha256:88d1c60bac2044a409154e895abb9d74c8ff5d034fb70f3e1f7c3ae96206bc0c", - "sha256:915a6b6b916fc66edec886fc71b60284e447d8fa39d22b879af7ae6efccca90f", - "sha256:a2c977909557439d0f17dc82adaea84e48374950d53416efc0b8451a594d42c3", - "sha256:ac226f37fc429b386d6447df6256dc958c28dd602f86f950072febf886995f80", - "sha256:b03cdf8a4e15929adf47e5e40a0ddeea1d63b65cf59c22553c12417a0c7ccbf4", - "sha256:c86ecd9d3da3d91e96da5f4a43d9c4fe35c5698b0633e91f171ba9468d112a8b", - "sha256:cad114d8673adab76b3602c28c461c613b7be3da28415500e42aed47415eb561", - "sha256:cb0a7ea9aa1c108924e31f1204a1e2534af255dbaa24ecbb8c05f47341a7b6f1", - "sha256:d30a018fc03fd1e83c75d40b8a156ef541d0b56b6403b63754e1cc96889849d9", - "sha256:d47b6530c55c092a9d841a12c8b3ad838bd639bebf6660a3df9dae83d4ab83c1", - "sha256:e8a054dbb8947718820be2ed6953d66b912ec2795f282725efdd08381a11b0d0", - "sha256:ec345caf15ae2c61540812500979e92f2989c6b6d4d13d21bdc82908043b3265" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==24.1a1" - }, - "click": { - "hashes": [ - "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", - "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" - ], - "markers": "python_version >= '3.7'", - "version": "==8.1.7" - }, - "frozenlist": { - "hashes": [ - "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7", - "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98", - "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad", - "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5", - "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae", - "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e", - "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a", - "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701", - "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d", - "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6", - "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6", - "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106", - "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75", - "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868", - "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a", - "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0", - "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1", - "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826", - "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec", - "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6", - "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950", - "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19", - "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0", - "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8", - "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a", - "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09", - "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86", - "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c", - "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5", - "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b", - "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b", - "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d", - "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0", - "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea", - "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776", - "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a", - "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897", - "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7", - "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09", - "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9", - "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe", - "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd", - "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742", - "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09", - "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0", - "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932", - "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1", - "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a", - "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49", - "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d", - "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7", - "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480", - "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89", - "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e", - "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b", - "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82", - "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb", - "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068", - "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8", - "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b", - "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb", - "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2", - "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11", - "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b", - "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc", - "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0", - "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497", - "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17", - "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0", - "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2", - "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439", - "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5", - "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac", - "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825", - "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887", - "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced", - "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74" - ], - "markers": "python_version >= '3.8'", - "version": "==1.4.1" - }, - "idna": { - "hashes": [ - "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca", - "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f" - ], - "markers": "python_version >= '3.5'", - "version": "==3.6" - }, - "multidict": { - "hashes": [ - "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9", - "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8", - "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03", - "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710", - "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161", - "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664", - "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569", - "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067", - "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313", - "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706", - "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2", - "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636", - "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49", - "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93", - "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603", - "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0", - "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60", - "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4", - "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e", - "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1", - "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60", - "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951", - "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc", - "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe", - "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95", - "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d", - "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8", - "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed", - "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2", - "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775", - "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87", - "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c", - "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2", - "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98", - "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3", - "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe", - "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78", - "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660", - "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176", - "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e", - "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988", - "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c", - "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c", - "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0", - "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449", - "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f", - "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde", - "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5", - "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d", - "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac", - "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a", - "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9", - "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca", - "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11", - "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35", - "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063", - "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b", - "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982", - "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258", - "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1", - "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52", - "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480", - "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7", - "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461", - "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d", - "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc", - "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779", - "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a", - "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547", - "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0", - "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171", - "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf", - "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d", - "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba" - ], - "markers": "python_version >= '3.7'", - "version": "==6.0.4" - }, - "mypy-extensions": { - "hashes": [ - "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", - "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782" - ], - "markers": "python_version >= '3.5'", - "version": "==1.0.0" - }, - "packaging": { - "hashes": [ - "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", - "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" - ], - "markers": "python_version >= '3.7'", - "version": "==23.2" - }, - "pathspec": { - "hashes": [ - "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", - "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712" - ], - "markers": "python_version >= '3.8'", - "version": "==0.12.1" - }, - "platformdirs": { - "hashes": [ - "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380", - "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420" - ], - "markers": "python_version >= '3.8'", - "version": "==4.1.0" - }, - "yarl": { - "hashes": [ - "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51", - "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce", - "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559", - "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0", - "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81", - "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc", - "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4", - "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c", - "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130", - "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136", - "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e", - "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec", - "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7", - "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1", - "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455", - "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099", - "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129", - "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10", - "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142", - "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98", - "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa", - "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7", - "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525", - "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c", - "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9", - "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c", - "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8", - "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b", - "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf", - "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23", - "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd", - "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27", - "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f", - "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece", - "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434", - "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec", - "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff", - "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78", - "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d", - "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863", - "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53", - "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31", - "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15", - "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5", - "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b", - "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57", - "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3", - "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1", - "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f", - "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad", - "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c", - "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7", - "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2", - "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b", - "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2", - "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b", - "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9", - "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be", - "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e", - "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984", - "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4", - "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074", - "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2", - "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392", - "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91", - "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541", - "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf", - "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572", - "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66", - "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575", - "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14", - "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5", - "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1", - "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e", - "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551", - "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17", - "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead", - "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0", - "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe", - "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234", - "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0", - "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7", - "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34", - "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42", - "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385", - "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78", - "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be", - "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958", - "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749", - "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec" - ], - "markers": "python_version >= '3.7'", - "version": "==1.9.4" - } - } + "develop": {} } diff --git a/rio/commands/FlyByWire.py b/rio/commands/FlyByWire.py deleted file mode 100644 index 7bfe84c3..00000000 --- a/rio/commands/FlyByWire.py +++ /dev/null @@ -1,55 +0,0 @@ -import typing -import commands2 -from wpilib import RobotBase -from subsystems.drivesubsystem import DriveSubsystem - - -class FlyByWire(commands2.CommandBase): - """ - FlyByWire uses pure joystick inputs - to direct the robot. Tradionally, this - is the most direct way to command the robot. - """ - - def __init__( - self, - drivetrain: DriveSubsystem, - forward: typing.Callable[[], float], - rotation: typing.Callable[[], float], - ) -> None: - super().__init__() - - self.drivetrain = drivetrain # This is a 'local' instance of drivetrain - self.forward = forward # Forward command - self.rotation = rotation # Rotation command - - # Adding drivetrain as a requirement ensures no other command will interrupt us - self.addRequirements(self.drivetrain) - - def execute(self) -> None: - if RobotBase.isReal(): - self.drivetrain.arcadeDrive( - self.exponential_dampen(self.forward()) * -1, - self.piecewise_dampen(self.rotation()), - ) - else: - self.drivetrain.tankDriveVolts( - self.forward() + self.rotation(), - -self.forward() + self.rotation(), - ) - - def exponential_dampen(self, x): - """ - Uses a simple math function - to dampen the user input. - """ - - return x / 1.3 * -1 - - def piecewise_dampen(self, x): - """ - Uses multiple different equations to define - a dampened user input - """ - - return x / 2.25 diff --git a/rio/constants.py b/rio/constants.py new file mode 100644 index 00000000..b33c0d1c --- /dev/null +++ b/rio/constants.py @@ -0,0 +1,141 @@ +# Copyright (c) FIRST and other WPILib contributors. +# Open Source Software; you can modify and/or share it under the terms of +# the WPILib BSD license file in the root directory of this project. + +""" +The constants module is a convenience place for teams to hold robot-wide +numerical or boolean constants. Don't use this for any other purpose! +""" + + +import math + +from wpimath import units +from wpimath.geometry import Translation2d +from wpimath.kinematics import SwerveDrive4Kinematics +from wpimath.trajectory import TrapezoidProfileRadians + +from rev import CANSparkMax + + +class NeoMotorConstants: + kFreeSpeedRpm = 5676 + + +class DriveConstants: + # Driving Parameters - Note that these are not the maximum capable speeds of + # the robot, rather the allowed maximum speeds + kMaxSpeedMetersPerSecond = 4.8 + kMaxAngularSpeed = math.tau # radians per second + + kDirectionSlewRate = 1.2 # radians per second + kMagnitudeSlewRate = 1.8 # percent per second (1 = 100%) + kRotationalSlewRate = 2.0 # percent per second (1 = 100%) + + # Chassis configuration + kTrackWidth = units.inchesToMeters(20.3937) + # Distance between centers of right and left wheels on robot + kWheelBase = units.inchesToMeters(20.25) + + # Distance between front and back wheels on robot + kModulePositions = [ + Translation2d(kWheelBase / 2, kTrackWidth / 2), + Translation2d(kWheelBase / 2, -kTrackWidth / 2), + Translation2d(-kWheelBase / 2, kTrackWidth / 2), + Translation2d(-kWheelBase / 2, -kTrackWidth / 2), + ] + kDriveKinematics = SwerveDrive4Kinematics(*kModulePositions) + + # Angular offsets of the modules relative to the chassis in radians + kFrontLeftChassisAngularOffset = 0 + kFrontRightChassisAngularOffset = 0 + kBackLeftChassisAngularOffset = 0 + kBackRightChassisAngularOffset = 0 + + # SPARK MAX CAN IDs + kFrontLeftDrivingCanId = 5 + kRearLeftDrivingCanId = 7 + kFrontRightDrivingCanId = 1 + kRearRightDrivingCanId = 3 + + kFrontLeftTurningCanId = 6 + kRearLeftTurningCanId = 8 + kFrontRightTurningCanId = 2 + kRearRightTurningCanId = 4 + + kGyroReversed = False + + +class ModuleConstants: + # The MAXSwerve module can be configured with one of three pinion gears: 12T, 13T, or 14T. + # This changes the drive speed of the module (a pinion gear with more teeth will result in a + # robot that drives faster). + kDrivingMotorPinionTeeth = 17 + + # Invert the turning encoder, since the output shaft rotates in the opposite direction of + # the steering motor in the MAXSwerve Module. + kTurningEncoderInverted = True + + # Calculations required for driving motor conversion factors and feed forward + kDrivingMotorFreeSpeedRps = NeoMotorConstants.kFreeSpeedRpm / 60 + kWheelDiameterMeters = 0.09525 + kWheelCircumferenceMeters = kWheelDiameterMeters * math.pi + # 45 teeth on the wheel's bevel gear, 22 teeth on the first-stage spur gear, 15 teeth on the bevel pinion + kDrivingMotorReduction = (60 * 34) / (kDrivingMotorPinionTeeth * 15) + kDriveWheelFreeSpeedRps = ( + kDrivingMotorFreeSpeedRps * kWheelCircumferenceMeters + ) / kDrivingMotorReduction + + kDrivingEncoderPositionFactor = ( + kWheelDiameterMeters * math.pi + ) / kDrivingMotorReduction # meters + kDrivingEncoderVelocityFactor = ( + (kWheelDiameterMeters * math.pi) / kDrivingMotorReduction + ) / 60.0 # meters per second + + kTurningEncoderPositionFactor = math.tau # radian + kTurningEncoderVelocityFactor = math.tau / 60.0 # radians per second + + kTurningEncoderPositionPIDMinInput = 0 # radian + kTurningEncoderPositionPIDMaxInput = kTurningEncoderPositionFactor # radian + + kDrivingP = 0.04 + kDrivingI = 0 + kDrivingD = 0 + kDrivingFF = 1 / kDriveWheelFreeSpeedRps + kDrivingMinOutput = -1 + kDrivingMaxOutput = 1 + + kTurningP = 1 + kTurningI = 0 + kTurningD = 0.1 + kTurningFF = 0 + kTurningMinOutput = -1 + kTurningMaxOutput = 1 + + kDrivingMotorIdleMode = CANSparkMax.IdleMode.kBrake + kTurningMotorIdleMode = CANSparkMax.IdleMode.kBrake + + kDrivingMotorCurrentLimit = 50 # amp + kTurningMotorCurrentLimit = 20 # amp + + +class OIConstants: + kDriverControllerPort = 0 + kDriveDeadband = 0.075 + + +class AutoConstants: + kMaxSpeedMetersPerSecond = 3 + kMaxAccelerationMetersPerSecondSquared = 3 + kMaxAngularSpeedRadiansPerSecond = math.pi + kMaxAngularSpeedRadiansPerSecondSquared = math.pi + + kPXController = 1 + kPYController = 1 + kPThetaController = 1 + + # Constraint for the motion profiled robot angle controller + kThetaControllerConstraints = TrapezoidProfileRadians.Constraints( + kMaxAngularSpeedRadiansPerSecond, kMaxAngularSpeedRadiansPerSecondSquared + ) diff --git a/rio/constants/__init__.py b/rio/constants/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/rio/constants/constants.py b/rio/constants/constants.py deleted file mode 100644 index ffe95648..00000000 --- a/rio/constants/constants.py +++ /dev/null @@ -1,44 +0,0 @@ -# Tidal Force Robotics -# 2022 - -import os -from sre_constants import CATEGORY_WORD -from wpilib import RobotBase -import yaml -import logging - -""" -Use this file only for storing non-changing constants. -""" - - -def load(fullPath: str): - # Try opening requested .yaml - with open(f"{fullPath}.yaml", "r") as yamlFile: - # Use yaml.safe_load to load the yaml into a dict - return yaml.safe_load(yamlFile) - - -def getConstants(identifier: str): - constants = {} - - # Clunky but it works - if RobotBase.isReal(): - path = "/home/lvuser/py/constants/" - else: - path = "constants/" - - try: - # Try opening requested .yaml - constants = load(f"{path}{identifier}") - except FileNotFoundError: - try: - # Try again but from one directory in (useful for unit testing) - constants = load(f"../{path}{identifier}") - except FileNotFoundError as e: - # If the file is not found, report it! - logging.error(f"{identifier} config not found!") - raise e - - # When all is done, return the important bits! - return constants diff --git a/rio/constants/robot_controls.yaml b/rio/constants/robot_controls.yaml deleted file mode 100644 index 6296b5ef..00000000 --- a/rio/constants/robot_controls.yaml +++ /dev/null @@ -1,34 +0,0 @@ -# This file defines the input -# and control scheme of the robot. -# this is orginized into control modes - -main mode: - driver: # using a stick controller - controller_port: 0 # What usb port the driver controller is on - - # Axis - ForwardAxis: 1 - SteerAxis: 2 - - # Buttons - HalfSpeedButton: 1 - DiffLock: 2 - Turn90: 3 - TurnAnti90: 4 - StartConfig: 5 - Slow: 10 - Crawl: 3 - - operator: # using an "x-box" controller - controller_port: 1 - - # Hold Buttons - Unclamp: 6 - Clamp: 5 - FindZero: 8 - hold: 3 - - # Presets/Modes - LowGoal: 1 - HighGoal: 4 - ManualMode: 7 \ No newline at end of file diff --git a/rio/constants/robot_hardware.yaml b/rio/constants/robot_hardware.yaml deleted file mode 100644 index 5af00073..00000000 --- a/rio/constants/robot_hardware.yaml +++ /dev/null @@ -1,51 +0,0 @@ -# This file defines the robot's -# physical dimensions. Things like -# Motor placement, max and min extensions -# of arms, and similar should go here. - -drivetrain: - max_velocity: 1.5 # Updated Never by Nobody - encoderConversionFactor: 21.43 # Updated 1/27 by Joe - - # All pose coordinates are in meters. - leftMotor: - Motor1Port: 2 # Updated 1/12 by Keegan - Motor2Port: 1 # Updated 1/12 by Keegan - EncoderPorts: [2, 1] # Updated 2/12 by Keegan - EncoderReversed: False # Updated Never by Nobody - Inverted: False # Updated Never by Nobody - - rightMotor: - Motor1Port: 3 # Updated 1/8 by Keegan - Motor2Port: 4 # Updated 1/8 by Keegan - EncoderPorts: [3, 4] # Updated Never by Nobody - EncoderReversed: True # Updated Never by Nobody - Inverted: True # Updated Never by Nobody - - navX: # NavX ids - can_id: 0 # Updated 1/13 by Keegan - yaw: 0 # Updated 1/13 by Keegan - pitch: 0 # Updated 1/13 by Keegan - roll: 0 # Updated 1/13 by Keegan - -arm: - elevatorMotor: # Drives the spool to move the lift in and out - MotorPort: 5 # Updated 1/22 by Keegan - Inverted: False # Updated 1/22 by Keegan - LimitSwitch: 0 # Updated 2/15 by Keegan - ConversionFactor: 1 # Updated 1/18 by Joe - Start: 0 # Updated 3/18 by Keegan - - ladderMotor: # Drives the lead screw to run the lift up and down - MotorPort: 6 # Updated 1/22 by Keegan - Inverted: False # Updated 1/22 by Keegan - ConversionFactor: 1 # Updated 1/18 by Joe - Start: 55 # Updated 3/18 by Keegan - - - -claw: - MotorPort: 7 # Updated 1/22 by Keegan - Inverted: False # Updated 1/22 by Keegan - EncoderPorts: 7 # Updated 2/11 by Keegan - EncoderReversed: False # Updated 1/22 by Keegan \ No newline at end of file diff --git a/rio/constants/robot_pid.yaml b/rio/constants/robot_pid.yaml deleted file mode 100644 index 1eabd5cf..00000000 --- a/rio/constants/robot_pid.yaml +++ /dev/null @@ -1,31 +0,0 @@ -# Constants for the robot PID - -drive: - # Diff lock - kStabilizationP: 0.011 - kStabilizationI: 0.0001 - kStabilizationD: 0 - - # TurnToAngle - kTurnP: 0.007 - kTurnI: 0.006 - kTurnD: 0.001 - - kMaxTurnRateDegPerS: 100 - kMaxTurnAccelerationDegPerSSquared: 300 - - kTurnToleranceDeg: 5 - kTurnRateToleranceDegPerS: 10 # degrees per second - -arm: - elevator: - kp: 0.075 - ki: 0 - kd: 0.1 - ff: 0 - - ladder: - kp: 0.1 - ki: 0 - kd: 0.1 - ff: 0 \ No newline at end of file diff --git a/rio/extras/deployData.py b/rio/extras/deployData.py deleted file mode 100644 index ec7a3f40..00000000 --- a/rio/extras/deployData.py +++ /dev/null @@ -1,28 +0,0 @@ -# Helper function for getting deploy data -import json - -from wpilib import RobotBase - - -def getDeployData(): - """ - Returns appropriate deploy data. - """ - - fakedata = { - "git-desc": "week0-69-g42096-dirty", - "git-branch": "sim/sim", - "deploy-host": "SimulatedLaptop", - "deploy-user": "SimUser", - "code-path": "/sim/simulatedrobot", - "deploy-date": "never", - } - - if RobotBase.isReal(): - try: - with open("/home/lvuser/py/deploy.json") as fp: - return json.load(fp) - except FileNotFoundError: - return fakedata - else: - return fakedata diff --git a/rio/robot.py b/rio/robot.py index 132a3cbe..bbce6218 100644 --- a/rio/robot.py +++ b/rio/robot.py @@ -5,74 +5,35 @@ # the WPILib BSD license file in the root directory of this project. # -import typing -import logging - -import wpilib import commands2 -import commands2.cmd - -import robotcontainer - -""" -The VM is configured to automatically run this class, and to call the functions corresponding to -each mode, as described in the TimedRobot documentation. If you change the name of this class or -the package after creating this project, you must also update the build.gradle file in the -project. -""" - - -class UnnamedToaster(commands2.TimedCommandRobot): - """ - Our default robot class, pass it to wpilib.run - Command v2 robots are encouraged to inherit from TimedCommandRobot, which - has an implementation of robotPeriodic which runs the scheduler for you - """ - - def robotInit(self) -> None: - """ - This function is run when the robot is first started up and should be used for any - initialization code. - """ +import wpilib - wpilib.CameraServer.launch() +from robotcontainer import RobotContainer - self.autonomousCommand: typing.Optional[commands2.Command] = None +class MyRobot(commands2.TimedCommandRobot): + def robotInit(self): # Instantiate our RobotContainer. This will perform all our button bindings, and put our # autonomous chooser on the dashboard. - self.container = robotcontainer.RobotContainer() - - def teleopInit(self) -> None: - # This makes sure that the autonomous stops running when - # teleop starts running. If you want the autonomous to - # continue until interrupted by another command, remove - # this line or comment it out. - if self.autonomousCommand is not None: - self.autonomousCommand.cancel() - - def disabledInit(self) -> None: - """This function is called once each time the robot enters Disabled mode.""" - - def disabledPeriodic(self) -> None: - """This function is called periodically when disabled""" + self.container = RobotContainer() + self.autonomousCommand = None def autonomousInit(self) -> None: - """This autonomous runs the autonomous command selected by your RobotContainer class.""" self.autonomousCommand = self.container.getAutonomousCommand() - # schedule the autonomous command (example) - if self.autonomousCommand is not None: + if self.autonomousCommand: self.autonomousCommand.schedule() - else: - logging.warning("no auto command?") - def autonomousPeriodic(self) -> None: - """This function is called periodically during autonomous""" + def teleopInit(self) -> None: + if self.autonomousCommand: + self.autonomousCommand.cancel() - def teleopPeriodic(self) -> None: - """This function is called periodically during operator control""" + # def teleopPeriodic(self) -> None: + # self.container.robotDrive.drive(0.1, 0.1, 0, False, False) def testInit(self) -> None: - # Cancels all running commands at the start of test mode commands2.CommandScheduler.getInstance().cancelAll() + + +if __name__ == "__main__": + wpilib.run(MyRobot) diff --git a/rio/robot_requirements.txt b/rio/robot_requirements.txt index b41433e5..026e15cb 100644 --- a/rio/robot_requirements.txt +++ b/rio/robot_requirements.txt @@ -11,4 +11,5 @@ robotpy-cscore robotpy-ctre robotpy-hal robotpy-rev -wpilib \ No newline at end of file +robotpy-navx +wpilib diff --git a/rio/robotcontainer.py b/rio/robotcontainer.py index c0d5d4ac..e52e4e32 100644 --- a/rio/robotcontainer.py +++ b/rio/robotcontainer.py @@ -1,25 +1,22 @@ -import wpilib +import math import commands2 -import commands2.cmd -import commands2.button - -# Constants -from constants.constants import getConstants - -# Subsystems -from subsystems.drivesubsystem import DriveSubsystem - -# Commands -from commands.FlyByWire import FlyByWire +import wpimath +import wpilib -# Autonomous +from commands2 import cmd +from commands2.button import CommandJoystick -# NetworkTables -from ntcore import NetworkTableInstance +from wpimath.controller import ( + PIDController, + ProfiledPIDControllerRadians, + HolonomicDriveController, +) +from wpimath.geometry import Pose2d, Rotation2d, Translation2d +from wpimath.trajectory import TrajectoryConfig, TrajectoryGenerator -# Misc -from extras.deployData import getDeployData +from constants import AutoConstants, DriveConstants, OIConstants +from subsystems.drivesubsystem import DriveSubsystem class RobotContainer: @@ -28,81 +25,116 @@ class RobotContainer: "declarative" paradigm, very little robot logic should actually be handled in the :class:`.Robot` periodic methods (other than the scheduler calls). Instead, the structure of the robot (including subsystems, commands, and button mappings) should be declared here. - """ - def __init__(self): - """The container for the robot. Contains subsystems, OI devices, and commands.""" - # Configure networktables - self.configureNetworktables() - - # Setup constants - self.controlConsts = getConstants("robot_controls") - self.hardConsts = getConstants("robot_hardware") - self.pidConsts = getConstants("robot_pid") - self.driverConsts = self.controlConsts["main mode"]["driver"] - self.operatorConsts = self.controlConsts["main mode"]["operator"] - + def __init__(self) -> None: # The robot's subsystems self.robotDrive = DriveSubsystem() - # The driver's controller - self.driverController = commands2.button.CommandJoystick( - self.driverConsts["controller_port"] - ) - # The operators controller - self.operatorController = commands2.button.CommandJoystick( - self.operatorConsts["controller_port"] - ) + # The driver's controller + self.driverController = CommandJoystick(0) # Configure the button bindings self.configureButtonBindings() - # Setup all autonomous routines - self.configureAutonomous() - - # Default drive command + # Configure default commands self.robotDrive.setDefaultCommand( - FlyByWire( - self.robotDrive, - lambda: -self.driverController.getRawAxis( - self.driverConsts["ForwardAxis"], - ), - lambda: self.driverController.getRawAxis( - self.driverConsts["SteerAxis"], + # The left stick controls translation of the robot. + # Turning is controlled by the X axis of the right stick. + commands2.cmd.run( + lambda: self.robotDrive.drive( + # -0.1, + # 0, + # 0, + wpimath.applyDeadband( + self.driverController.getRawAxis(1), + OIConstants.kDriveDeadband, # TODO: Use constants to set these controls + ) + * 0.3, + wpimath.applyDeadband( + self.driverController.getRawAxis(0), + OIConstants.kDriveDeadband, # TODO: Use constants to set these controls + ) + * 0.3, + -wpimath.applyDeadband( + self.driverController.getRawAxis(2), + OIConstants.kDriveDeadband, # TODO: Use constants to set these controls + ) + * 0.3, + False, + True, ), + self.robotDrive, ) ) - def configureButtonBindings(self): + def configureButtonBindings(self) -> None: """ - Use this method to define your button->command mappings. Buttons can be created via the button - factories on commands2.button.CommandGenericHID or one of its - subclasses (commands2.button.CommandJoystick or command2.button.CommandXboxController). + Use this method to define your button->command mappings. Buttons can be created by + instantiating a :GenericHID or one of its subclasses (Joystick or XboxController), + and then passing it to a JoystickButton. """ - pass - def configureAutonomous(self): - pass + def disablePIDSubsystems(self) -> None: + """Disables all ProfiledPIDSubsystem and PIDSubsystem instances. + This should be called on robot disable to prevent integral windup.""" - def configureNetworktables(self): - # Configure networktables - self.nt = NetworkTableInstance.getDefault() - self.sd = self.nt.getTable("SmartDashboard") + def getAutonomousCommand(self) -> commands2.Command: + """Use this to pass the autonomous command to the main {@link Robot} class. - # Subtables - self.build_table = self.sd.getSubTable("BuildData") + :returns: + command to run in autonomous + """ + # Create config for trajectory + config = TrajectoryConfig( + AutoConstants.kMaxSpeedMetersPerSecond, + AutoConstants.kMaxAccelerationMetersPerSecondSquared, + ) + # Add kinematics to ensure max speed is actually obeyed + config.setKinematics(DriveConstants.kDriveKinematics) + + # An example trajectory to follow. All units in meters. + exampleTrajectory = TrajectoryGenerator.generateTrajectory( + # Start at the origin facing the +X direction + Pose2d(0, 0, Rotation2d(0)), + # Pass through these two interior waypoints, making an 's' curve path + [Translation2d(1, 1), Translation2d(2, -1)], + # End 3 meters straight ahead of where we started, facing forward + Pose2d(3, 0, Rotation2d(0)), + config, + ) - # Build data (May need to be moved to a dedicated function to be updated more than once) - data = getDeployData() - for key in data: - key_entry = self.build_table.getEntry(str(key)) - key_entry.setString(str(data[key])) + thetaController = ProfiledPIDControllerRadians( + AutoConstants.kPThetaController, + 0, + 0, + AutoConstants.kThetaControllerConstraints, + ) + thetaController.enableContinuousInput(-math.pi, math.pi) - def getAutonomousCommand(self) -> commands2.Command: - """ - Use this to pass the autonomous command to the main :class:`.Robot` class. - :returns: the command to run in autonomous - """ - # return self.autoChooser.getSelected() - return None + holoController = HolonomicDriveController( + PIDController(AutoConstants.kPXController, 0, 0), + PIDController(AutoConstants.kPYController, 0, 0), + thetaController, + ) + + swerveControllerCommand = commands2.SwerveControllerCommand( + exampleTrajectory, + self.robotDrive.getPose, # Functional interface to feed supplier + DriveConstants.kDriveKinematics, + # Position controller + holoController, + self.robotDrive.setModuleStates, + (self.robotDrive,), + ) + + # Reset odometry to the starting pose of the trajectory. + self.robotDrive.resetOdometry(exampleTrajectory.initialPose()) + + # Run path following command, then stop at the end. + return swerveControllerCommand.andThen( + cmd.run( + lambda: self.robotDrive.drive(0, 0, 0, False, False), + self.robotDrive, + ) + ) diff --git a/rio/simgui-ds.json b/rio/simgui-ds.json index c57e37c3..6b37128a 100644 --- a/rio/simgui-ds.json +++ b/rio/simgui-ds.json @@ -1,25 +1,18 @@ { - "System Joysticks": { - "window": { - "visible": false - } - }, "keyboardJoysticks": [ { "axisConfig": [ { - "decKey": 69, - "decayRate": 0.0, - "incKey": 82, - "keyRate": 0.009999999776482582 + "decKey": 83, + "incKey": 87 }, { - "decKey": 87, - "incKey": 83 + "decKey": 68, + "incKey": 65 }, { - "decKey": 65, - "incKey": 68 + "decKey": 81, + "incKey": 69 } ], "axisCount": 3, @@ -28,67 +21,6 @@ 90, 88, 67, - 86, - 86, - 86, - 86, - 86, - 86, - 86 - ], - "povConfig": [ - { - "key0": 328, - "key135": 323, - "key180": 322, - "key225": 321, - "key270": 324, - "key315": 327, - "key45": 329, - "key90": 326 - } - ], - "povCount": 1 - }, - { - "axisConfig": [ - { - "decKey": 263, - "incKey": 262 - }, - { - "decKey": 265, - "incKey": 264 - }, - { - "decKey": 265, - "incKey": 264 - }, - { - "decKey": 265, - "incKey": 264 - }, - { - "decKey": 265, - "incKey": 264 - }, - { - "decKey": 265, - "incKey": 264 - } - ], - "axisCount": 6, - "buttonCount": 10, - "buttonKeys": [ - 77, - 44, - 46, - 47, - 86, - 86, - 86, - 86, - 86, 86 ], "povCount": 0 @@ -116,6 +48,11 @@ ], "povCount": 0 }, + { + "axisCount": 0, + "buttonCount": 0, + "povCount": 0 + }, { "axisCount": 0, "buttonCount": 0, @@ -126,10 +63,6 @@ { "guid": "Keyboard0", "name": "Driver Joystick" - }, - { - "guid": "Keyboard1", - "name": "Operator Stick" } ] } diff --git a/rio/simgui-window.json b/rio/simgui-window.json index a5c7242c..22ae3678 100644 --- a/rio/simgui-window.json +++ b/rio/simgui-window.json @@ -5,67 +5,50 @@ "MainWindow": { "GLOBAL": { "fps": "120", - "height": "757", + "height": "720", "maximized": "0", "style": "0", "userScale": "2", - "width": "1451", - "xpos": "170", - "ypos": "163" - } - }, - "Table": { - "0x542B5671,2": { - "Column 0 Width": "262", - "Column 1 Width": "350", - "RefScale": "13" + "width": "1280", + "xpos": "447", + "ypos": "289" } }, "Window": { - "###/SmartDashboard/Autonomous": { - "Collapsed": "0", - "Pos": "188,23", - "Size": "254,54" - }, - "###/SmartDashboard/Field": { - "Collapsed": "0", - "Pos": "4,301", - "Size": "438,242" - }, "###FMS": { "Collapsed": "0", - "Pos": "3,608", + "Pos": "5,540", "Size": "283,146" }, "###Joysticks": { "Collapsed": "0", - "Pos": "402,553", - "Size": "796,200" + "Pos": "291,574", + "Size": "796,138" }, "###NetworkTables": { "Collapsed": "0", - "Pos": "444,23", - "Size": "750,529" + "Pos": "269,170", + "Size": "750,395" }, "###NetworkTables Info": { "Collapsed": "0", - "Pos": "250,130", + "Pos": "269,27", "Size": "750,145" }, "###Other Devices": { "Collapsed": "0", - "Pos": "1199,21", - "Size": "250,734" + "Pos": "1025,20", + "Size": "250,695" }, "###System Joysticks": { "Collapsed": "0", - "Pos": "3,383", + "Pos": "5,350", "Size": "192,218" }, "###Timing": { "Collapsed": "0", - "Pos": "4,123", - "Size": "135,173" + "Pos": "5,150", + "Size": "135,150" }, "Debug##Default": { "Collapsed": "0", diff --git a/rio/simgui.json b/rio/simgui.json index 6c3c86fa..4f4a6cec 100644 --- a/rio/simgui.json +++ b/rio/simgui.json @@ -1,22 +1,7 @@ { "HALProvider": { "Other Devices": { - "SPARK MAX [1]": { - "header": { - "open": true - } - }, - "SPARK MAX [2]": { - "header": { - "open": true - } - }, - "SPARK MAX [3]": { - "header": { - "open": true - } - }, - "navX-Sensor[4]": { + "ADIS16448[4]": { "header": { "open": true } @@ -25,45 +10,13 @@ }, "NTProvider": { "types": { - "/FMSInfo": "FMSInfo", - "/SmartDashboard/Autonomous": "String Chooser", - "/SmartDashboard/Field": "Field2d" - }, - "windows": { - "/SmartDashboard/Autonomous": { - "window": { - "visible": true - } - }, - "/SmartDashboard/Field": { - "window": { - "visible": true - } - } + "/FMSInfo": "FMSInfo" } }, "NetworkTables": { - "Retained Values": { - "open": false - }, "transitory": { "SmartDashboard": { - "Autonomous": { - "open": true - }, - "BuildData": { - "open": true - }, - "Drivetrain": { - "open": true - }, - "Field": { - "open": true - }, - "Pose": { - "open": true - }, - "Test": { + "Swerve": { "open": true }, "open": true diff --git a/rio/subsystems/drivesubsystem.py b/rio/subsystems/drivesubsystem.py index d516114a..9d7f7940 100644 --- a/rio/subsystems/drivesubsystem.py +++ b/rio/subsystems/drivesubsystem.py @@ -1,161 +1,303 @@ -# Robot +import math +import typing + import wpilib -import wpilib.drive -import commands2 + +from commands2 import Subsystem +from wpimath.filter import SlewRateLimiter +from wpimath.geometry import Pose2d, Rotation2d +from wpimath.kinematics import ( + ChassisSpeeds, + SwerveModuleState, + SwerveDrive4Kinematics, + SwerveDrive4Odometry, +) + +from navx import AHRS + from ntcore import NetworkTableInstance -from wpimath.geometry import Pose2d -from wpimath.kinematics import DifferentialDriveOdometry -from wpilib import Field2d +from constants import DriveConstants -# Constants -from constants.constants import getConstants +import utils.swerveutils as swerveutils -# Vendor Libs -from rev import CANSparkMax, CANSparkMaxLowLevel -from navx import AHRS +from utils.dummygyro import DummyGyro +from .mikeswervemodule import MikeSwerveModule -class DriveSubsystem(commands2.Subsystem): + +class DriveSubsystem(Subsystem): def __init__(self) -> None: super().__init__() + + # Create MAXSwerveModules + self.frontLeft = MikeSwerveModule( + DriveConstants.kFrontLeftDrivingCanId, + DriveConstants.kFrontLeftTurningCanId, + DriveConstants.kFrontLeftChassisAngularOffset, + ) + + self.frontRight = MikeSwerveModule( + DriveConstants.kFrontRightDrivingCanId, + DriveConstants.kFrontRightTurningCanId, + DriveConstants.kFrontRightChassisAngularOffset, + ) + + self.rearLeft = MikeSwerveModule( + DriveConstants.kRearLeftDrivingCanId, + DriveConstants.kRearLeftTurningCanId, + DriveConstants.kBackLeftChassisAngularOffset, + ) + + self.rearRight = MikeSwerveModule( + DriveConstants.kRearRightDrivingCanId, + DriveConstants.kRearRightTurningCanId, + DriveConstants.kBackRightChassisAngularOffset, + ) + # Configure networktables self.nt = NetworkTableInstance.getDefault() self.sd = self.nt.getTable("SmartDashboard") - # network tables - self.nt = NetworkTableInstance.getDefault() - self.sd = self.nt.getTable("SmartDashboard") + # The gyro sensor + if wpilib.RobotBase.isReal(): + self.gyro = AHRS.create_spi() + else: + # Bug with navx init! For sim/unit testing just use the ADIS + self.gyro = DummyGyro() - # Hardware consts - constants = getConstants("robot_hardware") - self.driveConst = constants["drivetrain"] # All the drivetrain consts - self.leftCosnt = self.driveConst["leftMotor"] # Left specific - self.rightCosnt = self.driveConst["rightMotor"] # Right specific + # Slew rate filter variables for controlling lateral acceleration + self.currentRotation = 0.0 + self.currentTranslationDir = 0.0 + self.currentTranslationMag = 0.0 - # The motors on the left side of the drive. - self.leftMotor1 = CANSparkMax( - self.leftCosnt["Motor1Port"], - CANSparkMaxLowLevel.MotorType.kBrushless, - ) - self.leftMotor2 = CANSparkMax( - self.leftCosnt["Motor2Port"], - CANSparkMaxLowLevel.MotorType.kBrushless, + self.magLimiter = SlewRateLimiter(DriveConstants.kMagnitudeSlewRate) + self.rotLimiter = SlewRateLimiter(DriveConstants.kRotationalSlewRate) + self.prevTime = wpilib.Timer.getFPGATimestamp() + + # Odometry class for tracking robot pose + self.odometry = SwerveDrive4Odometry( + DriveConstants.kDriveKinematics, + Rotation2d.fromDegrees(self.gyro.getAngle()), + ( + self.frontLeft.getPosition(), + self.frontRight.getPosition(), + self.rearLeft.getPosition(), + self.rearRight.getPosition(), + ), ) - # Combine left motors into one group - self.leftMotors = wpilib.MotorControllerGroup( - self.leftMotor1, - self.leftMotor2, + def periodic(self) -> None: + # Update the odometry in the periodic block + self.odometry.update( + Rotation2d.fromDegrees(self.gyro.getAngle()), + ( + self.frontLeft.getPosition(), + self.frontRight.getPosition(), + self.rearLeft.getPosition(), + self.rearRight.getPosition(), + ), ) - self.leftMotors.setInverted(self.leftCosnt["Inverted"]) - # The motors on the right side of the drive. - self.rightMotor1 = CANSparkMax( - self.rightCosnt["Motor1Port"], - CANSparkMaxLowLevel.MotorType.kBrushless, + # desired + self.sd.putNumber( + "Swerve/FL desired", self.frontLeft.desiredState.angle.degrees() ) - self.rightMotor2 = CANSparkMax( - self.rightCosnt["Motor2Port"], - CANSparkMaxLowLevel.MotorType.kBrushless, + self.sd.putNumber( + "Swerve/FR desired", self.frontRight.desiredState.angle.degrees() ) - - # Combine left motors into one group - self.rightMotors = wpilib.MotorControllerGroup( - self.rightMotor1, - self.rightMotor2, + self.sd.putNumber( + "Swerve/RL desired", self.rearLeft.desiredState.angle.degrees() + ) + self.sd.putNumber( + "Swerve/RR desired", self.rearRight.desiredState.angle.degrees() ) - self.rightMotors.setInverted(self.rightCosnt["Inverted"]) - # self.rightMotors.setInverted(False) - # This fixes a bug in rev firmware involving flash settings. - self.leftMotor1.setInverted(False) - self.leftMotor2.setInverted(False) - self.rightMotor1.setInverted(False) - self.rightMotor2.setInverted(False) + # actual + self.sd.putNumber("Swerve/FL", self.frontLeft.getState().angle.degrees()) + self.sd.putNumber("Swerve/FR", self.frontRight.getState().angle.degrees()) + self.sd.putNumber("Swerve/RL", self.rearLeft.getState().angle.degrees()) + self.sd.putNumber("Swerve/RR", self.rearRight.getState().angle.degrees()) - # The robot's drivetrain kinematics - self.drive = wpilib.drive.DifferentialDrive(self.leftMotors, self.rightMotors) + def getPose(self) -> Pose2d: + """Returns the currently-estimated pose of the robot. - # The left-side drive encoder - self.leftEncoder = self.leftMotor1.getEncoder() + :returns: The pose. + """ + return self.odometry.getPose() - # The right-side drive encoder - self.rightEncoder = self.rightMotor2.getEncoder() + def resetOdometry(self, pose: Pose2d) -> None: + """Resets the odometry to the specified pose. - # PID Controllers - self.lPID = self.leftMotor1.getPIDController() - self.rPID = self.rightMotor1.getPIDController() + :param pose: The pose to which to set the odometry. - # Setup the conversion factors for the motor controllers - # TODO: Because rev is rev, there are a lot of problems that need to be addressed. - # https://www.chiefdelphi.com/t/spark-max-encoder-setpositionconversionfactor-not-doing-anything/396629 - self.leftEncoder.setPositionConversionFactor( - 1 / self.driveConst["encoderConversionFactor"] - ) - self.rightEncoder.setPositionConversionFactor( - 1 / self.driveConst["encoderConversionFactor"] + """ + self.odometry.resetPosition( + Rotation2d.fromDegrees(self.gyro.getAngle()), + ( + self.frontLeft.getPosition(), + self.frontRight.getPosition(), + self.rearLeft.getPosition(), + self.rearRight.getPosition(), + ), + pose, ) - # Gyro - self.ahrs = AHRS.create_spi() # creates navx object + def drive( + self, + xSpeed: float, + ySpeed: float, + rot: float, + fieldRelative: bool, + rateLimit: bool, + ) -> None: + """Method to drive the robot using joystick info. - # Robot odometry - self.field = Field2d() - self.odometry = DifferentialDriveOdometry( - self.ahrs.getRotation2d(), - self.leftEncoder.getPosition(), - self.rightEncoder.getPosition(), - ) + :param xSpeed: Speed of the robot in the x direction (forward). + :param ySpeed: Speed of the robot in the y direction (sideways). + :param rot: Angular rate of the robot. + :param fieldRelative: Whether the provided x and y speeds are relative to the + field. + :param rateLimit: Whether to enable rate limiting for smoother control. + """ - # Enable braking - self.rightMotor1.setIdleMode(CANSparkMax.IdleMode.kBrake) - self.rightMotor2.setIdleMode(CANSparkMax.IdleMode.kBrake) - self.leftMotor1.setIdleMode(CANSparkMax.IdleMode.kBrake) - self.leftMotor2.setIdleMode(CANSparkMax.IdleMode.kBrake) + xSpeedCommanded = xSpeed + ySpeedCommanded = ySpeed - def arcadeDrive(self, fwd: float, rot: float): - """ - Drives the robot using arcade controls. + if rateLimit: + # Convert XY to polar for rate limiting + inputTranslationDir = math.atan2(ySpeed, xSpeed) + inputTranslationMag = math.hypot(xSpeed, ySpeed) - :param fwd: the commanded forward movement - :param rot: the commanded rotation - """ - self.drive.arcadeDrive(fwd, rot) + # Calculate the direction slew rate based on an estimate of the lateral acceleration + if self.currentTranslationMag != 0.0: + directionSlewRate = abs( + DriveConstants.kDirectionSlewRate / self.currentTranslationMag + ) + else: + directionSlewRate = 500.0 + # some high number that means the slew rate is effectively instantaneous - def tankDriveVolts(self, leftVolts, rightVolts): - """Control the robot's drivetrain with voltage inputs for each side.""" - # Set the voltage of the left side. - # inverting this delays the KP issue but doesn't fix it - self.leftMotors.setVoltage(leftVolts) + currentTime = wpilib.Timer.getFPGATimestamp() + elapsedTime = currentTime - self.prevTime + angleDif = swerveutils.angleDifference( + inputTranslationDir, self.currentTranslationDir + ) + if angleDif < 0.45 * math.pi: + self.currentTranslationDir = swerveutils.stepTowardsCircular( + self.currentTranslationDir, + inputTranslationDir, + directionSlewRate * elapsedTime, + ) + self.currentTranslationMag = self.magLimiter.calculate( + inputTranslationMag + ) - # Set the voltage of the right side. - self.rightMotors.setVoltage(rightVolts) + elif angleDif > 0.85 * math.pi: + # some small number to avoid floating-point errors with equality checking + # keep currentTranslationDir unchanged + if self.currentTranslationMag > 1e-4: + self.currentTranslationMag = self.magLimiter.calculate(0.0) + else: + self.currentTranslationDir = swerveutils.wrapAngle( + self.currentTranslationDir + math.pi + ) + self.currentTranslationMag = self.magLimiter.calculate( + inputTranslationMag + ) - # print(f"({leftVolts}, {rightVolts})") + else: + self.currentTranslationDir = swerveutils.stepTowardsCircular( + self.currentTranslationDir, + inputTranslationDir, + directionSlewRate * elapsedTime, + ) + self.currentTranslationMag = self.magLimiter.calculate(0.0) - # Resets the timer for this motor's MotorSafety - self.drive.feed() + self.prevTime = currentTime - # Reset the encoders - self.resetEncoders() + xSpeedCommanded = self.currentTranslationMag * math.cos( + self.currentTranslationDir + ) + ySpeedCommanded = self.currentTranslationMag * math.sin( + self.currentTranslationDir + ) + self.currentRotation = self.rotLimiter.calculate(rot) - def setMaxOutput(self, maxOutput: float): - """ - Sets the max output of the drive. Useful for scaling the drive to drive more slowly. - :param maxOutput: the maximum output to which the drive will be constrained + else: + self.currentRotation = rot + + # Convert the commanded speeds into the correct units for the drivetrain + xSpeedDelivered = xSpeedCommanded * DriveConstants.kMaxSpeedMetersPerSecond + ySpeedDelivered = ySpeedCommanded * DriveConstants.kMaxSpeedMetersPerSecond + rotDelivered = self.currentRotation * DriveConstants.kMaxAngularSpeed + + swerveModuleStates = DriveConstants.kDriveKinematics.toSwerveModuleStates( + ChassisSpeeds.fromFieldRelativeSpeeds( + xSpeedDelivered, + ySpeedDelivered, + rotDelivered, + Rotation2d.fromDegrees(self.gyro.getAngle()), + ) + if fieldRelative + else ChassisSpeeds(xSpeedDelivered, ySpeedDelivered, rotDelivered) + ) + fl, fr, rl, rr = SwerveDrive4Kinematics.desaturateWheelSpeeds( + swerveModuleStates, DriveConstants.kMaxSpeedMetersPerSecond + ) + self.frontLeft.setDesiredState(fl) + self.frontRight.setDesiredState(fr) + self.rearLeft.setDesiredState(rl) + self.rearRight.setDesiredState(rr) + + def setX(self) -> None: + """Sets the wheels into an X formation to prevent movement.""" + self.frontLeft.setDesiredState(SwerveModuleState(0, Rotation2d.fromDegrees(45))) + self.frontRight.setDesiredState( + SwerveModuleState(0, Rotation2d.fromDegrees(-45)) + ) + self.rearLeft.setDesiredState(SwerveModuleState(0, Rotation2d.fromDegrees(-45))) + self.rearRight.setDesiredState(SwerveModuleState(0, Rotation2d.fromDegrees(45))) + + def setModuleStates( + self, + desiredStates: typing.Tuple[ + SwerveModuleState, SwerveModuleState, SwerveModuleState, SwerveModuleState + ], + ) -> None: + """Sets the swerve ModuleStates. + + :param desiredStates: The desired SwerveModule states. """ - self.drive.setMaxOutput(maxOutput) + fl, fr, rl, rr = SwerveDrive4Kinematics.desaturateWheelSpeeds( + desiredStates, DriveConstants.kMaxSpeedMetersPerSecond + ) + self.frontLeft.setDesiredState(fl) + self.frontRight.setDesiredState(fr) + self.rearLeft.setDesiredState(rl) + self.rearRight.setDesiredState(rr) - def resetEncoders(self): + def resetEncoders(self) -> None: """Resets the drive encoders to currently read a position of 0.""" - self.leftEncoder.setPosition(0) - self.rightEncoder.setPosition(0) + self.frontLeft.resetEncoders() + self.rearLeft.resetEncoders() + self.frontRight.resetEncoders() + self.rearRight.resetEncoders() - # https://docs.wpilib.org/en/stable/docs/software/kinematics-and-odometry/differential-drive-odometry.html#resetting-the-robot-pose - self.odometry.resetPosition( - self.ahrs.getRotation2d(), - self.leftEncoder.getPosition(), - -self.rightEncoder.getPosition(), - Pose2d(), - ) + def zeroHeading(self) -> None: + """Zeroes the heading of the robot.""" + self.gyro.reset() + + def getHeading(self) -> float: + """Returns the heading of the robot. + + :returns: the robot's heading in degrees, from -180 to 180 + """ + return Rotation2d.fromDegrees(self.gyro.getAngle()).degrees() + + def getTurnRate(self) -> float: + """Returns the turn rate of the robot. + + :returns: The turn rate of the robot, in degrees per second + """ + return self.gyro.getRate() * (-1.0 if DriveConstants.kGyroReversed else 1.0) diff --git a/rio/subsystems/mikeswervemodule.py b/rio/subsystems/mikeswervemodule.py new file mode 100644 index 00000000..15dd4740 --- /dev/null +++ b/rio/subsystems/mikeswervemodule.py @@ -0,0 +1,174 @@ +from rev import CANSparkMax, SparkMaxAbsoluteEncoder, CANSparkLowLevel +from wpimath.geometry import Rotation2d +from wpimath.kinematics import SwerveModuleState, SwerveModulePosition + +from constants import ModuleConstants + + +class MikeSwerveModule: + def __init__( + self, drivingCANId: int, turningCANId: int, chassisAngularOffset: float + ) -> None: + """Constructs a Mike Swerve Module, a custom module designed in house. + + This code is based on Rev's swerve module the Max Swerve module, and + the original code for that can be found here + https://github.com/robotpy/robotpy-rev/blob/main/examples/maxswerve/subsystems/maxswervemodule.py + """ + + self.chassisAngularOffset = 0 + self.desiredState = SwerveModuleState(0.0, Rotation2d()) + + self.drivingSparkMax = CANSparkMax( + drivingCANId, CANSparkLowLevel.MotorType.kBrushless + ) + self.turningSparkMax = CANSparkMax( + turningCANId, CANSparkLowLevel.MotorType.kBrushless + ) + + # Factory reset, so we get the SPARKS MAX to a known state before configuring + # them. This is useful in case a SPARK MAX is swapped out. + self.drivingSparkMax.restoreFactoryDefaults() + self.turningSparkMax.restoreFactoryDefaults() + + # Setup encoders and PID controllers for the driving and turning SPARKS MAX. + self.drivingEncoder = self.drivingSparkMax.getEncoder() + self.turningEncoder = self.turningSparkMax.getAbsoluteEncoder( + SparkMaxAbsoluteEncoder.Type.kDutyCycle + ) + self.drivingPIDController = self.drivingSparkMax.getPIDController() + self.turningPIDController = self.turningSparkMax.getPIDController() + self.drivingPIDController.setFeedbackDevice(self.drivingEncoder) + self.turningPIDController.setFeedbackDevice(self.turningEncoder) + + # Apply position and velocity conversion factors for the driving encoder. The + # native units for position and velocity are rotations and RPM, respectively, + # but we want meters and meters per second to use with WPILib's swerve APIs. + self.drivingEncoder.setPositionConversionFactor( + ModuleConstants.kDrivingEncoderPositionFactor + ) + self.drivingEncoder.setVelocityConversionFactor( + ModuleConstants.kDrivingEncoderVelocityFactor + ) + + # Apply position and velocity conversion factors for the turning encoder. We + # want these in radians and radians per second to use with WPILib's swerve + # APIs. + self.turningEncoder.setPositionConversionFactor( + ModuleConstants.kTurningEncoderPositionFactor + ) + self.turningEncoder.setVelocityConversionFactor( + ModuleConstants.kTurningEncoderVelocityFactor + ) + + # Invert the turning encoder, since the output shaft rotates in the opposite direction of + # the steering motor in the MAXSwerve Module. + self.turningEncoder.setInverted(ModuleConstants.kTurningEncoderInverted) + + # Enable PID wrap around for the turning motor. This will allow the PID + # controller to go through 0 to get to the setpoint i.e. going from 350 degrees + # to 10 degrees will go through 0 rather than the other direction which is a + # longer route. + self.turningPIDController.setPositionPIDWrappingEnabled(True) + self.turningPIDController.setPositionPIDWrappingMinInput( + ModuleConstants.kTurningEncoderPositionPIDMinInput + ) + self.turningPIDController.setPositionPIDWrappingMaxInput( + ModuleConstants.kTurningEncoderPositionPIDMaxInput + ) + + # Set the PID gains for the driving motor. Note these are example gains, and you + # may need to tune them for your own robot! + self.drivingPIDController.setP(ModuleConstants.kDrivingP) + self.drivingPIDController.setI(ModuleConstants.kDrivingI) + self.drivingPIDController.setD(ModuleConstants.kDrivingD) + self.drivingPIDController.setFF(ModuleConstants.kDrivingFF) + self.drivingPIDController.setOutputRange( + ModuleConstants.kDrivingMinOutput, ModuleConstants.kDrivingMaxOutput + ) + + # Set the PID gains for the turning motor. Note these are example gains, and you + # may need to tune them for your own robot! + self.turningPIDController.setP(ModuleConstants.kTurningP) + self.turningPIDController.setI(ModuleConstants.kTurningI) + self.turningPIDController.setD(ModuleConstants.kTurningD) + self.turningPIDController.setFF(ModuleConstants.kTurningFF) + self.turningPIDController.setOutputRange( + ModuleConstants.kTurningMinOutput, ModuleConstants.kTurningMaxOutput + ) + + self.drivingSparkMax.setIdleMode(ModuleConstants.kDrivingMotorIdleMode) + self.turningSparkMax.setIdleMode(ModuleConstants.kTurningMotorIdleMode) + self.drivingSparkMax.setSmartCurrentLimit( + ModuleConstants.kDrivingMotorCurrentLimit + ) + self.turningSparkMax.setSmartCurrentLimit( + ModuleConstants.kTurningMotorCurrentLimit + ) + + # Save the SPARK MAX configurations. If a SPARK MAX browns out during + # operation, it will maintain the above configurations. + self.drivingSparkMax.burnFlash() + self.turningSparkMax.burnFlash() + + self.chassisAngularOffset = chassisAngularOffset + self.desiredState.angle = Rotation2d(self.turningEncoder.getPosition()) + self.drivingEncoder.setPosition(0) + + def getState(self) -> SwerveModuleState: + """Returns the current state of the module. + + :returns: The current state of the module. + """ + # Apply chassis angular offset to the encoder position to get the position + # relative to the chassis. + return SwerveModuleState( + self.drivingEncoder.getVelocity(), + Rotation2d(self.turningEncoder.getPosition() - self.chassisAngularOffset), + ) + + def getPosition(self) -> SwerveModulePosition: + """Returns the current position of the module. + + :returns: The current position of the module. + """ + # Apply chassis angular offset to the encoder position to get the position + # relative to the chassis. + return SwerveModulePosition( + self.drivingEncoder.getPosition(), + Rotation2d(self.turningEncoder.getPosition() - self.chassisAngularOffset), + ) + + def setDesiredState(self, desiredState: SwerveModuleState) -> None: + """Sets the desired state for the module. + + :param desiredState: Desired state with speed and angle. + + """ + # Apply chassis angular offset to the desired state. + correctedDesiredState = SwerveModuleState() + correctedDesiredState.speed = desiredState.speed + correctedDesiredState.angle = -desiredState.angle + Rotation2d( + self.chassisAngularOffset + ) + + # Optimize the reference state to avoid spinning further than 90 degrees. + optimizedDesiredState = SwerveModuleState.optimize( + correctedDesiredState, Rotation2d(self.turningEncoder.getPosition()) + ) + + # Command driving and turning SPARKS MAX towards their respective setpoints. + self.drivingPIDController.setReference( + optimizedDesiredState.speed, CANSparkMax.ControlType.kVelocity + ) + self.turningPIDController.setReference( + optimizedDesiredState.angle.radians(), CANSparkMax.ControlType.kPosition + ) + + self.desiredState = desiredState + + def resetEncoders(self) -> None: + """ + Zeroes all the SwerveModule encoders. + """ + self.drivingEncoder.setPosition(0) diff --git a/rio/tests/pyfrc_test.py b/rio/tests/pyfrc_test.py index 55ee6b49..bbe80a0c 100644 --- a/rio/tests/pyfrc_test.py +++ b/rio/tests/pyfrc_test.py @@ -1,18 +1,6 @@ """ -This module provides pyfrc tests useful for almost any robot. -use `python -m robotpy test` to run +This test module imports tests that come with pyfrc, and can be used +to test basic functionality of just about any robot. """ from pyfrc.tests import * - -# Testable modules -from constants.constants import getConstants -from subsystems.drivesubsystem import DriveSubsystem - - -def test_yaml(): - assert len(getConstants("robot_controls")) > 0 - - -def test_nothing(): - assert True # Tests if true is true! diff --git a/rio/utils/dummygyro.py b/rio/utils/dummygyro.py new file mode 100644 index 00000000..7329053c --- /dev/null +++ b/rio/utils/dummygyro.py @@ -0,0 +1,7 @@ +# Used to bypass bugs in the gyro init during sim +class DummyGyro: + def __init__(self): + pass + + def getAngle(self) -> float: + return 0.0 diff --git a/rio/utils/swerveutils.py b/rio/utils/swerveutils.py new file mode 100644 index 00000000..ad6eccf3 --- /dev/null +++ b/rio/utils/swerveutils.py @@ -0,0 +1,87 @@ +import math + + +def stepTowards(current: float, target: float, stepsize: float) -> float: + """Steps a value towards a target with a specified step size. + + :param current: The current or starting value. Can be positive or negative. + :param target: The target value the algorithm will step towards. Can be positive or negative. + :param stepsize: The maximum step size that can be taken. + + :returns: The new value for {@code current} after performing the specified step towards the specified target. + """ + + if abs(current - target) <= stepsize: + return target + + elif target < current: + return current - stepsize + + else: + return current + stepsize + + +def stepTowardsCircular(current: float, target: float, stepsize: float) -> float: + """Steps a value (angle) towards a target (angle) taking the shortest path with a specified step size. + + :param current: The current or starting angle (in radians). Can lie outside the 0 to 2*PI range. + :param target: The target angle (in radians) the algorithm will step towards. Can lie outside the 0 to 2*PI range. + :param stepsize: The maximum step size that can be taken (in radians). + + :returns: The new angle (in radians) for {@code current} after performing the specified step towards the specified target. + This value will always lie in the range 0 to 2*PI (exclusive). + """ + + current = wrapAngle(current) + target = wrapAngle(target) + + stepDirection = math.copysign(target - current, 1) + difference = abs(current - target) + + if difference <= stepsize: + return target + elif difference > math.pi: # does the system need to wrap over eventually? + # handle the special case where you can reach the target in one step while also wrapping + if ( + current + math.tau - target < stepsize + or target + math.tau - current < stepsize + ): + return target + else: + # this will handle wrapping gracefully + return wrapAngle(current - stepDirection * stepsize) + else: + return current + stepDirection * stepsize + + +def angleDifference(angleA: float, angleB: float) -> float: + """Finds the (unsigned) minimum difference between two angles including calculating across 0. + + :param angleA: An angle (in radians). + :param angleB: An angle (in radians). + + :returns: The (unsigned) minimum difference between the two angles (in radians). + """ + difference = abs(angleA - angleB) + return math.tau - difference if difference > math.pi else difference + + +def wrapAngle(angle: float) -> float: + """Wraps an angle until it lies within the range from 0 to 2*PI (exclusive). + + :param angle: The angle (in radians) to wrap. Can be positive or negative and can lie multiple wraps outside the output range. + + :returns: An angle (in radians) from 0 and 2*PI (exclusive). + """ + + twoPi = math.tau + + # Handle this case separately to avoid floating point errors with the floor after the division in the case below + if angle == twoPi: + return 0.0 + elif angle > twoPi: + return angle - twoPi * math.floor(angle / twoPi) + elif angle < 0.0: + return angle + twoPi * (math.floor((-angle) / twoPi) + 1) + else: + return angle