diff --git a/src/proto/message_translation/power_frame_msg.hpp b/src/proto/message_translation/power_frame_msg.hpp index 6caa0e3de9..c180d7e4af 100644 --- a/src/proto/message_translation/power_frame_msg.hpp +++ b/src/proto/message_translation/power_frame_msg.hpp @@ -85,6 +85,13 @@ void inline setPowerMsg(TbotsProto_PowerFrame& frame, frame.power_msg.power_status = status; } +void inline setPowerMsg(TbotsProto_PowerFrame& frame, + const TbotsProto_DribblerControl& dribble_control) +{ + frame.which_power_msg = TbotsProto_PowerFrame_dribbler_control_tag; + frame.power_msg.dribbler_control = dribble_control; +} + /** * Creates a nanopb power status msg with provided fields * @@ -316,4 +323,11 @@ std::unique_ptr inline createTbotsPowerStatus( proto_status->ParseFromString(std::string(buffer.begin(), buffer.end())); return proto_status; } + +TbotsProto_DribblerControl inline createNanoPbDribblerControl(int rpm) +{ + TbotsProto_DribblerControl control = TbotsProto_DribblerControl_init_default; + control.dribbler_speed = rpm; + return control; +} #endif diff --git a/src/proto/power_frame_msg.proto b/src/proto/power_frame_msg.proto index 9c708bf083..3a2b91d2c4 100644 --- a/src/proto/power_frame_msg.proto +++ b/src/proto/power_frame_msg.proto @@ -32,13 +32,19 @@ message PowerPulseControl Geneva.Slot geneva_slot = 2; } +message DribblerControl +{ + uint32 dribbler_speed = 1; // Changed from uint8 to have better rpm control +} + message PowerFrame { uint32 length = 1; uint32 crc = 2; oneof power_msg { - PowerPulseControl power_control = 3; - PowerStatus power_status = 4; + PowerPulseControl power_control = 3; + PowerStatus power_status = 4; + DribblerControl dribbler_control = 5; } } diff --git a/src/software/embedded/BUILD b/src/software/embedded/BUILD index e5bba4bd99..0651ff70ee 100644 --- a/src/software/embedded/BUILD +++ b/src/software/embedded/BUILD @@ -58,6 +58,8 @@ cc_library( deps = [ ":primitive_executor", "//proto:tbots_cc_proto", + "//software/embedded/motor_controller", + "//software/embedded/motor_controller:motor_board", "//software/embedded/services:imu", "//software/embedded/services:motor", "//software/embedded/services:power", diff --git a/src/software/embedded/ansible/requirements_lock.txt b/src/software/embedded/ansible/requirements_lock.txt index 77dfeb01c6..2f2f0a02fd 100644 --- a/src/software/embedded/ansible/requirements_lock.txt +++ b/src/software/embedded/ansible/requirements_lock.txt @@ -8,9 +8,9 @@ ansible==11.9.0 \ --hash=sha256:528ca5a408f11cf1fea00daea7570e68d40e167be38b90c119a7cb45729e4921 \ --hash=sha256:79b087ef38105b93e0e092e7013a0f840e154a6a8ce9b5fddd1b47593adc542a # via -r software/embedded/ansible/requirements.in -ansible-core==2.18.9 \ - --hash=sha256:25206e1aac3bd30d95649a5ccf0d3646461d02b4dc265b5959e33b7ccd6f23f8 \ - --hash=sha256:a5f4a02aad5843e990ff7be1b92dd658a8b230de713ea643920e683ebf980da1 +ansible-core==2.18.17 \ + --hash=sha256:556815258f84a57349b63474479506b2a8431a85661fd3f53a5c11894b7a3f25 \ + --hash=sha256:ae746d8b76c45cc7ee4123fba1f9ea1e3df2ed36a5d2b7ace7e88205bacc73f9 # via ansible cffi==2.0.0 \ --hash=sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb \ @@ -98,61 +98,56 @@ cffi==2.0.0 \ --hash=sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453 \ --hash=sha256:fe562eb1a64e67dd297ccc4f5addea2501664954f2692b69a76449ec7913ecbf # via cryptography -cryptography==46.0.1 \ - --hash=sha256:0a17377fa52563d730248ba1f68185461fff36e8bc75d8787a7dd2e20a802b7a \ - --hash=sha256:0ca4be2af48c24df689a150d9cd37404f689e2968e247b6b8ff09bff5bcd786f \ - --hash=sha256:0d1922d9280e08cde90b518a10cd66831f632960a8d08cb3418922d83fce6f12 \ - --hash=sha256:0dfb7c88d4462a0cfdd0d87a3c245a7bc3feb59de101f6ff88194f740f72eda6 \ - --hash=sha256:0ff483716be32690c14636e54a1f6e2e1b7bf8e22ca50b989f88fa1b2d287080 \ - --hash=sha256:13e67c4d3fb8b6bc4ef778a7ccdd8df4cd15b4bcc18f4239c8440891a11245cc \ - --hash=sha256:15b5fd9358803b0d1cc42505a18d8bca81dabb35b5cfbfea1505092e13a9d96d \ - --hash=sha256:1cd6d50c1a8b79af1a6f703709d8973845f677c8e97b1268f5ff323d38ce8475 \ - --hash=sha256:2dd339ba3345b908fa3141ddba4025568fa6fd398eabce3ef72a29ac2d73ad75 \ - --hash=sha256:341fb7a26bc9d6093c1b124b9f13acc283d2d51da440b98b55ab3f79f2522ead \ - --hash=sha256:34f04b7311174469ab3ac2647469743720f8b6c8b046f238e5cb27905695eb2a \ - --hash=sha256:41c281a74df173876da1dc9a9b6953d387f06e3d3ed9284e3baae3ab3f40883a \ - --hash=sha256:449ef2b321bec7d97ef2c944173275ebdab78f3abdd005400cc409e27cd159ab \ - --hash=sha256:45f790934ac1018adeba46a0f7289b2b8fe76ba774a88c7f1922213a56c98bc1 \ - --hash=sha256:48948940d0ae00483e85e9154bb42997d0b77c21e43a77b7773c8c80de532ac5 \ - --hash=sha256:4c49eda9a23019e11d32a0eb51a27b3e7ddedde91e099c0ac6373e3aacc0d2ee \ - --hash=sha256:504e464944f2c003a0785b81668fe23c06f3b037e9cb9f68a7c672246319f277 \ - --hash=sha256:534b96c0831855e29fc3b069b085fd185aa5353033631a585d5cd4dd5d40d657 \ - --hash=sha256:6ef1488967e729948d424d09c94753d0167ce59afba8d0f6c07a22b629c557b2 \ - --hash=sha256:7176a5ab56fac98d706921f6416a05e5aff7df0e4b91516f450f8627cda22af3 \ - --hash=sha256:7411c910fb2a412053cf33cfad0153ee20d27e256c6c3f14d7d7d1d9fec59fd5 \ - --hash=sha256:757af4f6341ce7a1e47c326ca2a81f41d236070217e5fbbad61bbfe299d55d28 \ - --hash=sha256:7823bc7cdf0b747ecfb096d004cc41573c2f5c7e3a29861603a2871b43d3ef32 \ - --hash=sha256:7fab1187b6c6b2f11a326f33b036f7168f5b996aedd0c059f9738915e4e8f53a \ - --hash=sha256:84ef1f145de5aee82ea2447224dc23f065ff4cc5791bb3b506615957a6ba8128 \ - --hash=sha256:92e8cfe8bd7dd86eac0a677499894862cd5cc2fd74de917daa881d00871ac8e7 \ - --hash=sha256:9394c7d5a7565ac5f7d9ba38b2617448eba384d7b107b262d63890079fad77ca \ - --hash=sha256:9495d78f52c804b5ec8878b5b8c7873aa8e63db9cd9ee387ff2db3fffe4df784 \ - --hash=sha256:9873bf7c1f2a6330bdfe8621e7ce64b725784f9f0c3a6a55c3047af5849f920e \ - --hash=sha256:9babb7818fdd71394e576cf26c5452df77a355eac1a27ddfa24096665a27f8fd \ - --hash=sha256:9e8776dac9e660c22241b6587fae51a67b4b0147daa4d176b172c3ff768ad736 \ - --hash=sha256:9ed64e5083fa806709e74fc5ea067dfef9090e5b7a2320a49be3c9df3583a2d8 \ - --hash=sha256:9f2c4cc63be3ef43c0221861177cee5d14b505cd4d4599a89e2cd273c4d3542a \ - --hash=sha256:9f40642a140c0c8649987027867242b801486865277cbabc8c6059ddef16dc8b \ - --hash=sha256:af84e8e99f1a82cea149e253014ea9dc89f75b82c87bb6c7242203186f465129 \ - --hash=sha256:b9c79af2c3058430d911ff1a5b2b96bbfe8da47d5ed961639ce4681886614e70 \ - --hash=sha256:c52fded6383f7e20eaf70a60aeddd796b3677c3ad2922c801be330db62778e05 \ - --hash=sha256:cbb8e769d4cac884bb28e3ff620ef1001b75588a5c83c9c9f1fdc9afbe7f29b0 \ - --hash=sha256:d84c40bdb8674c29fa192373498b6cb1e84f882889d21a471b45d1f868d8d44b \ - --hash=sha256:db5597a4c7353b2e5fb05a8e6cb74b56a4658a2b7bf3cb6b1821ae7e7fd6eaa0 \ - --hash=sha256:e22801b61613ebdebf7deb18b507919e107547a1d39a3b57f5f855032dd7cfb8 \ - --hash=sha256:e34da95e29daf8a71cb2841fd55df0511539a6cdf33e6f77c1e95e44006b9b46 \ - --hash=sha256:e46710a240a41d594953012213ea8ca398cd2448fbc5d0f1be8160b5511104a0 \ - --hash=sha256:e94eb5fa32a8a9f9bf991f424f002913e3dd7c699ef552db9b14ba6a76a6313b \ - --hash=sha256:ec13b7105117dbc9afd023300fb9954d72ca855c274fe563e72428ece10191c0 \ - --hash=sha256:ed570874e88f213437f5cf758f9ef26cbfc3f336d889b1e592ee11283bb8d1c7 \ - --hash=sha256:ed957044e368ed295257ae3d212b95456bd9756df490e1ac4538857f67531fcc \ - --hash=sha256:ef648d2c690703501714588b2ba640facd50fd16548133b11b2859e8655a69da \ - --hash=sha256:efc9e51c3e595267ff84adf56e9b357db89ab2279d7e375ffcaf8f678606f3d9 \ - --hash=sha256:f736ab8036796f5a119ff8211deda416f8c15ce03776db704a7a4e17381cb2ef \ - --hash=sha256:f7a24ea78de345cfa7f6a8d3bde8b242c7fac27f2bd78fa23474ca38dfaeeab9 \ - --hash=sha256:f7de12fa0eee6234de9a9ce0ffcfa6ce97361db7a50b09b65c63ac58e5f22fc7 \ - --hash=sha256:f9b55038b5c6c47559aa33626d8ecd092f354e23de3c6975e4bb205df128a2a0 \ - --hash=sha256:fd4b5e2ee4e60425711ec65c33add4e7a626adef79d66f62ba0acfd493af282d +cryptography==48.0.0 \ + --hash=sha256:0890f502ddf7d9c6426129c3f49f5c0a39278ed7cd6322c8755ffca6ee675a13 \ + --hash=sha256:0c558d2cdffd8f4bbb30fc7134c74d2ca9a476f830bb053074498fbc86f41ed6 \ + --hash=sha256:16cd65b9330583e4619939b3a3843eec1e6e789744bb01e7c7e2e62e33c239c8 \ + --hash=sha256:18349bbc56f4743c8b12dc32e2bccb2cf83ee8b69a3bba74ef8ae857e26b3d25 \ + --hash=sha256:1e2d54c8be6152856a36f0882ab231e70f8ec7f14e93cf87db8a2ed056bf160c \ + --hash=sha256:22a5cb272895dce158b2cacdfdc3debd299019659f42947dbdac6f32d68fe832 \ + --hash=sha256:27241b1dc9962e056062a8eef1991d02c3a24569c95975bd2322a8a52c6e5e12 \ + --hash=sha256:2b4d59804e8408e2fea7d1fbaf218e5ec984325221db76e6a241a9abd6cdd95c \ + --hash=sha256:2eb992bbd4661238c5a397594c83f5b4dc2bc5b848c365c8f991b6780efcc5c7 \ + --hash=sha256:369a6348999f94bbd53435c894377b20ab95f25a9065c283570e70150d8abc3c \ + --hash=sha256:3cb07a3ed6431663cd321ea8a000a1314c74211f823e4177fefa2255e057d1ec \ + --hash=sha256:40ba1f85eaa6959837b1d51c9767e230e14612eea4ef110ee8854ada22da1bf5 \ + --hash=sha256:4defde8685ae324a9eb9d818717e93b4638ef67070ac9bc15b8ca85f63048355 \ + --hash=sha256:55b7718303bf06a5753dcdccf2f3945cf18ad7bffde41b61226e4db31ab89a9c \ + --hash=sha256:561215ea3879cb1cbbf272867e2efda62476f240fb58c64de6b393ae19246741 \ + --hash=sha256:58d00498e8933e4a194f3076aee1b4a97dfec1a6da444535755822fe5d8b0b86 \ + --hash=sha256:59baa2cb386c4f0b9905bd6eb4c2a79a69a128408fd31d32ca4d7102d4156321 \ + --hash=sha256:5a5ed8fde7a1d09376ca0b40e68cd59c69fe23b1f9768bd5824f54681626032a \ + --hash=sha256:5b012212e08b8dd5edc78ef54da83dd9892fd9105323b3993eff6bea65dc21d7 \ + --hash=sha256:5c3932f4436d1cccb036cb0eaef46e6e2db91035166f1ad6505c3c9d5a635920 \ + --hash=sha256:614d0949f4790582d2cc25553abd09dd723025f0c0e7c67376a1d77196743d6e \ + --hash=sha256:76341972e1eff8b4bea859f09c0d3e64b96ce931b084f9b9b7db8ef364c30eff \ + --hash=sha256:77a2ccbbe917f6710e05ba9adaa25fb5075620bf3ea6fb751997875aff4ae4bd \ + --hash=sha256:7995ef305d7165c3f11ae07f2517e5a4f1d5c18da1376a0a9ed496336b69e5f3 \ + --hash=sha256:7ce4bfae76319a532a2dc68f82cc32f5676ee792a983187dac07183690e5c66f \ + --hash=sha256:7e8eac43dfca5c4cccc6dad9a80504436fca53bb9bc3100a2386d730fbe6b602 \ + --hash=sha256:84cf79f0dc8b36ac5da873481716e87aef31fcfa0444f9e1d8b4b2cece142855 \ + --hash=sha256:8c7378637d7d88016fa6791c159f698b3d3eed28ebf844ac36b9dc04a14dae18 \ + --hash=sha256:8cd666227ef7af430aa5914a9910e0ddd703e75f039cef0825cd0da71b6b711a \ + --hash=sha256:906cbf0670286c6e0044156bc7d4af9cbb0ef6db9f73e52c3ec56ba6bdde5336 \ + --hash=sha256:9071196d81abc88b3516ac8cdfad32e2b66dd4a5393a8e68a961e9161ddc6239 \ + --hash=sha256:9249e3cd978541d665967ac2cb2787fd6a62bddf1e75b3e347a594d7dacf4f74 \ + --hash=sha256:984a20b0f62a26f48a3396c72e4bc34c66e356d356bf370053066b3b6d54634a \ + --hash=sha256:9be5aafa5736574f8f15f262adc81b2a9869e2cfe9014d52a44633905b40d52c \ + --hash=sha256:9c459db21422be75e2809370b829a87eb37f74cd785fc4aa9ea1e5f43b47cda4 \ + --hash=sha256:9ccdac7d40688ecb5a3b4a604b8a88c8002e3442d6c60aead1db2a89a041560c \ + --hash=sha256:a0e692c683f4df67815a2d258b324e66f4738bd7a96a218c826dce4f4bd05d8f \ + --hash=sha256:a5da777e32ffed6f85a7b2b3f7c5cbc88c146bfcd0a1d7baf5fcc6c52ee35dd4 \ + --hash=sha256:a64697c641c7b1b2178e573cbc31c7c6684cd56883a478d75143dbb7118036db \ + --hash=sha256:ad64688338ed4bc1a6618076ba75fd7194a5f1797ac60b47afe926285adb3166 \ + --hash=sha256:bd72e68b06bb1e96913f97dd4901119bc17f39d4586a5adf2d3e47bc2b9d58b5 \ + --hash=sha256:c17dfe85494deaeddc5ce251aebd1d60bbe6afc8b62071bb0b469431a000124f \ + --hash=sha256:c18684a7f0cc9a3cb60328f496b8e3372def7c5d2df39ac267878b05565aaaae \ + --hash=sha256:cc90c0b39b2e3c65ef52c804b72e3c58f8a04ab2a1871272798e5f9572c17d20 \ + --hash=sha256:db63bf618e5dea46c07de12e900fe1cdd2541e6dc9dbae772a70b7d4d4765f6a \ + --hash=sha256:ea8990436d914540a40ab24b6a77c0969695ed52f4a4874c5137ccf7045a7057 \ + --hash=sha256:ecde28a596bead48b0cfd2a1b4416c3d43074c2d785e3a398d7ec1fc4d0f7fbb \ + --hash=sha256:f5333311663ea94f75dd408665686aaf426563556bb5283554a3539177e03b8c \ + --hash=sha256:fdfef35d751d510fcef5252703621574364fec16418c4a1e5e1055248401054b # via ansible-core jinja2==3.1.6 \ --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ @@ -249,13 +244,13 @@ markupsafe==3.0.3 \ --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 # via jinja2 -packaging==25.0 \ - --hash=sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484 \ - --hash=sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f +packaging==26.2 \ + --hash=sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e \ + --hash=sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661 # via ansible-core -pycparser==2.23 \ - --hash=sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2 \ - --hash=sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934 +pycparser==3.0 \ + --hash=sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29 \ + --hash=sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992 # via cffi pyyaml==6.0.3 \ --hash=sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c \ @@ -269,12 +264,14 @@ pyyaml==6.0.3 \ --hash=sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0 \ --hash=sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b \ --hash=sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1 \ + --hash=sha256:22ba7cfcad58ef3ecddc7ed1db3409af68d023b7f940da23c6c2a1890976eda6 \ --hash=sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7 \ --hash=sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e \ --hash=sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007 \ --hash=sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310 \ --hash=sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4 \ --hash=sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9 \ + --hash=sha256:3ff07ec89bae51176c0549bc4c63aa6202991da2d9a6129d7aef7f1407d3f295 \ --hash=sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea \ --hash=sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0 \ --hash=sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e \ @@ -283,10 +280,12 @@ pyyaml==6.0.3 \ --hash=sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7 \ --hash=sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35 \ --hash=sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb \ + --hash=sha256:5cf4e27da7e3fbed4d6c3d8e797387aaad68102272f8f9752883bc32d61cb87b \ --hash=sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69 \ --hash=sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5 \ --hash=sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b \ --hash=sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c \ + --hash=sha256:6344df0d5755a2c9a276d4473ae6b90647e216ab4757f8426893b5dd2ac3f369 \ --hash=sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd \ --hash=sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824 \ --hash=sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198 \ @@ -303,6 +302,7 @@ pyyaml==6.0.3 \ --hash=sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28 \ --hash=sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3 \ --hash=sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5 \ + --hash=sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4 \ --hash=sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b \ --hash=sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf \ --hash=sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5 \ @@ -314,6 +314,7 @@ pyyaml==6.0.3 \ --hash=sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc \ --hash=sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c \ --hash=sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba \ + --hash=sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f \ --hash=sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917 \ --hash=sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5 \ --hash=sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26 \ @@ -321,6 +322,7 @@ pyyaml==6.0.3 \ --hash=sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b \ --hash=sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be \ --hash=sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c \ + --hash=sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3 \ --hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6 \ --hash=sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926 \ --hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0 diff --git a/src/software/embedded/motor_controller/BUILD b/src/software/embedded/motor_controller/BUILD index 26518edbfd..27f6eedf59 100644 --- a/src/software/embedded/motor_controller/BUILD +++ b/src/software/embedded/motor_controller/BUILD @@ -35,6 +35,7 @@ cc_library( "//proto/message_translation:tbots_protobuf", "//software/embedded:spi_utils", "//software/embedded/gpio", + "//software/embedded/services:power", "//software/logger", "//software/physics:euclidean_to_wheel", "@cppcrc", @@ -66,6 +67,7 @@ cc_binary( ], deps = [ ":motor_controller", + "//software/embedded/services:uart_communicator", "//software/logger", "//software/logger:network_logger", "@boost//:program_options", diff --git a/src/software/embedded/motor_controller/stspin_motor_controller.cpp b/src/software/embedded/motor_controller/stspin_motor_controller.cpp index 1c29915b4d..cfa6dc5296 100644 --- a/src/software/embedded/motor_controller/stspin_motor_controller.cpp +++ b/src/software/embedded/motor_controller/stspin_motor_controller.cpp @@ -22,10 +22,12 @@ using Crc8Autosar = crc_utils::crc; StSpinMotorController::StSpinMotorController( - const robot_constants::RobotConstants& robot_constants) + const robot_constants::RobotConstants& robot_constants, + std::shared_ptr uart) : robot_constants_(robot_constants), reset_gpio_(std::make_unique(RESET_GPIO_PIN, GpioDirection::OUTPUT, - GpioState::HIGH)) + GpioState::HIGH)), + uart_(uart) { for (const MotorIndex motor : driveMotors()) { @@ -84,7 +86,6 @@ void StSpinMotorController::updateFaults(const MotorIndex motor, // No faults return; } - // TODO #3748 Use a helper, stop regenerating the stream object. std::ostringstream oss; oss << "======= Faults For Motor " << motor << "=======\n"; @@ -178,7 +179,8 @@ int StSpinMotorController::readThenWriteVelocity(const MotorIndex motor, { if (motor == MotorIndex::DRIBBLER) { - return 0; + // Here target_velocity is treated as angular velocity with unit RPM + uart_->sendDribbleTarget(target_velocity); } const auto outgoing_frame = SetTargetSpeedFrame{ diff --git a/src/software/embedded/motor_controller/stspin_motor_controller.h b/src/software/embedded/motor_controller/stspin_motor_controller.h index 1a3c2209cb..a46d799aa9 100644 --- a/src/software/embedded/motor_controller/stspin_motor_controller.h +++ b/src/software/embedded/motor_controller/stspin_motor_controller.h @@ -5,6 +5,7 @@ #include "software/embedded/motor_controller/motor_fault_indicator.h" #include "software/embedded/motor_controller/motor_index.h" #include "software/embedded/motor_controller/stspin_types.h" +#include "software/embedded/services/uart_communicator.h" /** * Motor controller for controlling our 6th generation STSPIN motor drivers. @@ -16,8 +17,8 @@ class StSpinMotorController : public MotorController { public: - explicit StSpinMotorController( - const robot_constants::RobotConstants& robot_constants); + explicit StSpinMotorController(const robot_constants::RobotConstants& robot_constants, + std::shared_ptr power_service); void setup() override; @@ -92,6 +93,8 @@ class StSpinMotorController : public MotorController std::unordered_map motor_status_; + std::shared_ptr uart_; + /** * Opens a SPI file descriptor for the given motor. * diff --git a/src/software/embedded/motor_controller/stspin_motor_controller_test.cpp b/src/software/embedded/motor_controller/stspin_motor_controller_test.cpp index 1f54b929f5..c2f71bbf2b 100644 --- a/src/software/embedded/motor_controller/stspin_motor_controller_test.cpp +++ b/src/software/embedded/motor_controller/stspin_motor_controller_test.cpp @@ -6,6 +6,7 @@ #include #include +#include "software/embedded/services/uart_communicator.h" #include "software/logger/logger.h" #include "software/logger/network_logger.h" @@ -45,9 +46,9 @@ class StSpinMotorControllerTest ss << motor << " "; } LOG(INFO) << "Enabled motors: " << ss.str(); - + const auto uart = std::make_shared(); const auto motor_controller = std::make_unique( - robot_constants::createRobotConstants()); + robot_constants::createRobotConstants(), uart); motor_controller->setup(); LOG(INFO) << "Motor controller setup complete"; diff --git a/src/software/embedded/services/BUILD b/src/software/embedded/services/BUILD index fa9571a16c..19cc76cf51 100644 --- a/src/software/embedded/services/BUILD +++ b/src/software/embedded/services/BUILD @@ -30,11 +30,7 @@ cc_library( hdrs = ["power.h"], linkopts = ["-latomic"], # Necessary due to not containing load/store for all sizes deps = [ - "//shared/uart_framing", - "//software/logger", - "//software/uart:boost_uart_communication", - "@boost//:asio", - "@boost//:filesystem", + ":uart_communicator", ], ) @@ -51,3 +47,16 @@ cc_library( "@eigen", ], ) + +cc_library( + name = "uart_communicator", + srcs = ["uart_communicator.cpp"], + hdrs = ["uart_communicator.h"], + deps = [ + "//shared/uart_framing", + "//software/logger", + "//software/uart:boost_uart_communication", + "@boost//:asio", + "@boost//:filesystem", + ], +) diff --git a/src/software/embedded/services/motor.cpp b/src/software/embedded/services/motor.cpp index 6c838b0c5a..f87237e77e 100644 --- a/src/software/embedded/services/motor.cpp +++ b/src/software/embedded/services/motor.cpp @@ -6,9 +6,10 @@ #include "software/embedded/motor_controller/tmc_motor_controller.h" #include "software/logger/logger.h" -MotorService::MotorService(const robot_constants::RobotConstants& robot_constants) +MotorService::MotorService(const robot_constants::RobotConstants& robot_constants, + std::unique_ptr motor_controller) : robot_constants_(robot_constants), - motor_controller_(setupMotorController()), + motor_controller_(std::move(motor_controller)), euclidean_to_four_wheel_(robot_constants), dribbler_target_rpm_(0), // placeholder, move to power_service drive_motor_mps_per_rpm_(2 * M_PI * robot_constants.wheel_radius_meters / 60), @@ -29,17 +30,7 @@ void MotorService::reset() motor_controller_->reset(); } -std::unique_ptr MotorService::setupMotorController() -{ - if constexpr (MOTOR_BOARD == MotorBoard::TRINAMIC) - { - return std::make_unique(); - } - else - { - return std::make_unique(robot_constants_); - } -} + TbotsProto::MotorStatus MotorService::createMotorStatus( const WheelSpace_t& current_wheel_velocities, const double dribbler_rpm) const diff --git a/src/software/embedded/services/motor.h b/src/software/embedded/services/motor.h index 445fb03ff5..19e7f81570 100644 --- a/src/software/embedded/services/motor.h +++ b/src/software/embedded/services/motor.h @@ -24,8 +24,10 @@ class MotorService * Service that interacts with the motors. * * @param robot_constants The robot constants + * @param motor_controller The motor controller */ - explicit MotorService(const robot_constants::RobotConstants& robot_constants); + explicit MotorService(const robot_constants::RobotConstants& robot_constants, + std::unique_ptr motor_controller); /** * Polls the motor service to execute the given motor control command and diff --git a/src/software/embedded/services/power.cpp b/src/software/embedded/services/power.cpp index c9c98f1ff8..5899f17d89 100644 --- a/src/software/embedded/services/power.cpp +++ b/src/software/embedded/services/power.cpp @@ -5,81 +5,11 @@ #include "proto/power_frame_msg.pb.h" -PowerService::PowerService() -{ - nanopb_command = createNanoPbPowerPulseControl(TbotsProto::PowerControl(), 0.0, 0, 0); - - if (!boost::filesystem::exists(DEVICE_SERIAL_PORT)) - { - throw std::runtime_error("USB not plugged into the Raspberry Pi"); - } - this->uart = std::make_unique(BAUD_RATE, DEVICE_SERIAL_PORT); - this->read_thread = std::thread(std::bind(&PowerService::continuousRead, this)); -} - -PowerService::~PowerService() -{ - is_running = false; - read_thread.join(); -} - -void PowerService::continuousRead() -{ - while (is_running) - { - tick(); - } -} - -void PowerService::tick() -{ - std::vector power_status; - try - { - uart->flushSerialPort(uart->flush_receive); - power_status = uart->serialRead(READ_BUFFER_SIZE); - } - catch (std::exception& e) - { - LOG(FATAL) << "Read thread has crashed" << e.what(); - } - - TbotsProto_PowerFrame status_frame = TbotsProto_PowerFrame_init_default; - if (!unmarshalUartPacket(power_status, status_frame)) - { - LOG(WARNING) << "Unmarshal failed"; - } - else - { - status = status_frame.power_msg.power_status; - } - - auto command = - nanopb_command.load(std::memory_order_relaxed); // get value atomically - auto frame = createUartFrame(command); - auto power_command_buffer = marshallUartPacket(frame); - - try - { - // Write power command - uart->flushSerialPort(uart->flush_send); - if (!uart->serialWrite(power_command_buffer)) - { - LOG(WARNING) << "Writing power command failed."; - } - } - catch (std::exception& e) - { - LOG(FATAL) << "ESP32 has disconnected. Power service has crashed" << e.what(); - } -} +PowerService::PowerService(std::shared_ptr uart) : uart_(uart) {} TbotsProto::PowerStatus PowerService::poll(const TbotsProto::PowerControl& command, double kick_coeff, int kick_constant, int chip_constant) { - // Store msg for later transmission - nanopb_command = - createNanoPbPowerPulseControl(command, kick_coeff, kick_constant, chip_constant); - return *createTbotsPowerStatus(status); + return uart_->sendChipKickCommand(command, kick_coeff, kick_constant, chip_constant); } diff --git a/src/software/embedded/services/power.h b/src/software/embedded/services/power.h index b479e5eec2..d19d3b60e5 100644 --- a/src/software/embedded/services/power.h +++ b/src/software/embedded/services/power.h @@ -4,9 +4,7 @@ #include #include "proto/power_frame_msg.pb.h" -#include "shared/uart_framing/uart_framing.hpp" -#include "software/logger/logger.h" -#include "software/uart/boost_uart_communication.h" +#include "software/embedded/services/uart_communicator.h" extern "C" { @@ -18,10 +16,9 @@ class PowerService public: /** * Service that interacts with the power board. - * Opens all the required ports and maintains them until destroyed. + * Connects to the UartCommunicator */ - PowerService(); - ~PowerService(); + PowerService(std::shared_ptr uart); /** * When the power service is polled it sends the given power control msg and @@ -33,28 +30,6 @@ class PowerService TbotsProto::PowerStatus poll(const TbotsProto::PowerControl& control, double kick_coeff, int kick_constant, int chip_constant); - /** - * Handler method called every time the timer expires a new read is requested - */ - void tick(); - private: - /** - * Initiates timer for serial reading - */ - void continuousRead(); - - std::thread read_thread; - std::atomic status; - std::atomic nanopb_command; - std::unique_ptr uart; - - // Constants - const size_t READ_BUFFER_SIZE = - getMarshalledSize(TbotsProto_PowerStatus TbotsProto_PowerStatus_init_default); - const std::string DEVICE_SERIAL_PORT = "/dev/ttyUSB0"; - static constexpr unsigned int BAUD_RATE = 460800; - - // Required flag to exit power service cleanly - bool is_running = true; + std::shared_ptr uart_; }; diff --git a/src/software/embedded/services/uart_communicator.cpp b/src/software/embedded/services/uart_communicator.cpp new file mode 100644 index 0000000000..651d5d7f27 --- /dev/null +++ b/src/software/embedded/services/uart_communicator.cpp @@ -0,0 +1,102 @@ +#include "software/embedded/services/uart_communicator.h" + +#include +#include + +#include "proto/power_frame_msg.pb.h" + +UartCommunicator::UartCommunicator() +{ + nanopb_command = createNanoPbPowerPulseControl(TbotsProto::PowerControl(), 0.0, 0, 0); + + if (!boost::filesystem::exists(DEVICE_SERIAL_PORT)) + { + throw std::runtime_error("USB not plugged into the Raspberry Pi"); + } + this->uart = std::make_unique(BAUD_RATE, DEVICE_SERIAL_PORT); + this->read_thread = std::thread(std::bind(&UartCommunicator::continuousRead, this)); +} + +UartCommunicator::~UartCommunicator() +{ + is_running = false; + read_thread.join(); +} + + +void UartCommunicator::sendDribbleTarget(int rpm) +{ + dribble_command = createNanoPbDribblerControl(rpm); + _new_dribble_command = true; +} + +TbotsProto::PowerStatus UartCommunicator::sendChipKickCommand( + const TbotsProto::PowerControl& command, double kick_coeff, int kick_constant, + int chip_constant) +{ + // Store msg for later transmission + nanopb_command = + createNanoPbPowerPulseControl(command, kick_coeff, kick_constant, chip_constant); + return *createTbotsPowerStatus(status); +} + +void UartCommunicator::tick() +{ + std::vector power_status; + try + { + uart->flushSerialPort(uart->flush_receive); + power_status = uart->serialRead(READ_BUFFER_SIZE); + } + catch (std::exception& e) + { + LOG(FATAL) << "Read thread has crashed" << e.what(); + } + + TbotsProto_PowerFrame status_frame = TbotsProto_PowerFrame_init_default; + if (!unmarshalUartPacket(power_status, status_frame)) + { + LOG(WARNING) << "Unmarshal failed"; + } + else + { + status = status_frame.power_msg.power_status; + } + + std::vector power_command_buffer; + if (_new_dribble_command) + { + auto command = + dribble_command.load(std::memory_order_relaxed); // get value atomically + _new_dribble_command = false; + power_command_buffer = marshallUartPacket(createUartFrame(command)); + } + else + { + auto command = + nanopb_command.load(std::memory_order_relaxed); // get value atomically + power_command_buffer = marshallUartPacket(createUartFrame(command)); + } + + try + { + // Write power command + uart->flushSerialPort(uart->flush_send); + if (!uart->serialWrite(power_command_buffer)) + { + LOG(WARNING) << "Writing power command failed."; + } + } + catch (std::exception& e) + { + LOG(FATAL) << "ESP32 has disconnected. Power service has crashed" << e.what(); + } +} + +void UartCommunicator::continuousRead() +{ + while (is_running) + { + tick(); + } +} diff --git a/src/software/embedded/services/uart_communicator.h b/src/software/embedded/services/uart_communicator.h new file mode 100644 index 0000000000..a6137f3898 --- /dev/null +++ b/src/software/embedded/services/uart_communicator.h @@ -0,0 +1,72 @@ +#pragma once + +#include +#include + +#include "proto/power_frame_msg.pb.h" +#include "shared/uart_framing/uart_framing.hpp" +#include "software/logger/logger.h" +#include "software/uart/boost_uart_communication.h" + +extern "C" +{ +#include "proto/power_frame_msg.pb.h" +} + +/** + * Communicates to the powerboard over uart. + */ +class UartCommunicator +{ + public: + /** + * Service that interacts with the power board. + * Opens all the required ports and maintains them until destroyed. + */ + UartCommunicator(); + ~UartCommunicator(); + + /** + * When the power service is polled it sends the given power control msg and + * returns the latest power status + * + * @param control The power control msg to send + * @return the latest power status + */ + TbotsProto::PowerStatus sendChipKickCommand(const TbotsProto::PowerControl& control, + double kick_coeff, int kick_constant, + int chip_constant); + + /** + * Set dribbler RPM + */ + void sendDribbleTarget(int rpm); + + /** + * Handler method called every time the timer expires a new read is requested + */ + virtual void tick(); + + protected: + /** + * Initiates timer for serial reading + */ + void continuousRead(); + + std::thread read_thread; + std::atomic status; + std::atomic nanopb_command; + std::unique_ptr uart; + + // Constants + const size_t READ_BUFFER_SIZE = + getMarshalledSize(TbotsProto_PowerStatus TbotsProto_PowerStatus_init_default); + const std::string DEVICE_SERIAL_PORT = "/dev/ttyUSB0"; + static constexpr unsigned int BAUD_RATE = 460800; + + // Required flag to exit power service cleanly + bool is_running = true; + + bool _new_dribble_command = false; + std::atomic dribble_command; +}; diff --git a/src/software/embedded/thunderloop.cpp b/src/software/embedded/thunderloop.cpp index 15916a04fe..71c666d431 100644 --- a/src/software/embedded/thunderloop.cpp +++ b/src/software/embedded/thunderloop.cpp @@ -10,9 +10,13 @@ #include "proto/tbots_software_msgs.pb.h" #include "shared/constants.h" #include "software/constants.h" +#include "software/embedded/motor_controller/motor_board.h" +#include "software/embedded/motor_controller/stspin_motor_controller.h" +#include "software/embedded/motor_controller/tmc_motor_controller.h" #include "software/embedded/primitive_executor.h" #include "software/embedded/services/imu.h" #include "software/embedded/services/motor.h" +#include "software/embedded/services/uart_communicator.h" #include "software/logger/logger.h" #include "software/logger/network_logger.h" #include "software/networking/tbots_network_exception.h" @@ -117,11 +121,22 @@ Thunderloop::Thunderloop(const robot_constants::RobotConstants& robot_constants, LOG(INFO) << "THUNDERLOOP: Network Service initialized! Next initializing Power Service"; - power_service_ = std::make_unique(); + std::shared_ptr uart = std::make_shared(); + power_service_ = std::make_unique(uart); LOG(INFO) << "THUNDERLOOP: Power Service initialized! Next initializing Motor Service"; - motor_service_ = std::make_unique(robot_constants); + if constexpr (MOTOR_BOARD == MotorBoard::TRINAMIC) + { + motor_service_ = std::make_unique( + robot_constants, std::make_unique()); + } + else + { + motor_service_ = std::make_unique( + robot_constants, + std::make_unique(robot_constants, uart)); + } g_motor_service = motor_service_.get(); motor_service_->setup(); diff --git a/src/software/power/BUILD b/src/software/power/BUILD index ad6a5a5b4f..c0657b4281 100644 --- a/src/software/power/BUILD +++ b/src/software/power/BUILD @@ -16,6 +16,13 @@ platformio_library( deps = [":pins"], ) +platformio_library( + name = "dribbler", + src = "dribbler.cpp", + hdr = "dribbler.h", + deps = [":pins"], +) + platformio_library( name = "geneva", src = "geneva.cpp", @@ -73,6 +80,7 @@ platformio_project( ":charger", ":chicker", ":control_executor", + ":dribbler", ":geneva", ":pins", ":power_monitor", diff --git a/src/software/power/dribbler.cpp b/src/software/power/dribbler.cpp new file mode 100644 index 0000000000..88c88d2631 --- /dev/null +++ b/src/software/power/dribbler.cpp @@ -0,0 +1,11 @@ +#include "dribbler.h" + +Dribbler::Dribbler() +{ + pinMode(DRIBBLER_PIN, OUTPUT); +} + +void Dribbler::dribble(uint32_t speed) +{ + analogWrite(DRIBBLER_PIN, speed); +} diff --git a/src/software/power/dribbler.h b/src/software/power/dribbler.h new file mode 100644 index 0000000000..87de4169f6 --- /dev/null +++ b/src/software/power/dribbler.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +/** + * Represents the dribbler on the power board + */ +class Dribbler +{ + public: + /** + * Creates a dribbler, setting up pins. + */ + Dribbler(); + + /** + * Sets the dribbler to the given duty cycle from 0 (always off) to 255 (always on) + */ + static void dribble(uint32_t speed); +}; diff --git a/src/software/power/pins.h b/src/software/power/pins.h index fdbdd9c20b..b5eb47e324 100644 --- a/src/software/power/pins.h +++ b/src/software/power/pins.h @@ -31,6 +31,9 @@ const uint8_t TXD2 = 22; const uint8_t PM_SDA = 13; const uint8_t PM_SCL = 14; +// Dribbler +const uint8_t DRIBBLER_PIN = 4; // When elec has a pin for this + // Timers const uint8_t CHICKER_PULSE_TIMER = 0; const uint8_t CHICKER_COOLDOWN_TIMER = 3; diff --git a/src/software/power/powerloop_main.cc b/src/software/power/powerloop_main.cc index 692f70bed8..102ecbb707 100644 --- a/src/software/power/powerloop_main.cc +++ b/src/software/power/powerloop_main.cc @@ -3,6 +3,7 @@ #include "chicker.h" #include "constants_platformio.h" #include "control_executor.h" +#include "dribbler.h" #include "geneva.h" #include "power_frame_msg_platformio.h" #include "power_monitor.h" @@ -34,6 +35,12 @@ std::shared_ptr chicker; std::shared_ptr monitor; std::shared_ptr geneva; std::shared_ptr executor; +std::shared_ptr dribbler; + +#define RAMP_FACTOR 4 +#define DRIBBLER_MAX_SPEED 11040 // Max RPM from spec +int dribble_target; +int dribbler_speed; void setup() { @@ -45,7 +52,10 @@ void setup() monitor = std::make_shared(); geneva = std::make_shared(); executor = std::make_shared(charger, chicker, geneva); + dribbler = std::make_shared(); charger->chargeCapacitors(); + dribbler_speed = 0; + dribble_target = 0; } void loop() @@ -63,8 +73,15 @@ void loop() if (unmarshalUartPacket(buffer, frame)) { // On successful decoding execute the given command - TbotsProto_PowerPulseControl control = frame.power_msg.power_control; - executor->execute(control); + if (frame.which_power_msg == TbotsProto_PowerFrame_power_control_tag) + { + executor->execute(frame.power_msg.power_control); + } + else if (frame.which_power_msg == + TbotsProto_PowerFrame_dribbler_control_tag) + { + dribble_target = frame.power_msg.dribbler_control.dribbler_speed; + } } buffer.clear(); @@ -87,6 +104,18 @@ void loop() monitor->getCurrentDrawAmp(), geneva->getCurrentSlot(), sequence_num++, chicker->getBreakBeamTripped()); + if (dribble_target <= dribbler_speed) + { + dribbler_speed = dribble_target; + } + else + { + // Ramp to speed + dribbler_speed = + dribbler_speed + (dribble_target - dribbler_speed) / RAMP_FACTOR + 1; + } + dribbler->dribble(dribbler_speed / DRIBBLER_MAX_SPEED * 255); + // Write sensor values out to Serial TbotsProto_PowerFrame status_frame = createUartFrame(status); std::vector packet = marshallUartPacket(status_frame);