{"id":1062,"date":"2017-04-09T17:29:48","date_gmt":"2017-04-09T16:29:48","guid":{"rendered":"http:\/\/ofalcao.pt\/blog\/?p=1062"},"modified":"2017-06-19T10:15:59","modified_gmt":"2017-06-19T09:15:59","slug":"triplex-an-holonomic-robot","status":"publish","type":"post","link":"https:\/\/ofalcao.pt\/blog\/2017\/triplex-an-holonomic-robot","title":{"rendered":"Triplex &#8211; an holonomic robot"},"content":{"rendered":"<div class=\"seriesmeta\">This post is part 1 of 3 of \u00a0<a href=\"https:\/\/ofalcao.pt\/blog\/series\/triplex\" class=\"series-303\" title=\"Triplex\">Triplex<\/a><\/div><p>A few months ago, trying to find an use for a new LEGO brick found in NEXO Knights sets, I made my first omni wheel. It worked but it was to fragile to be used in a robot so I decided to copy one of Isogawa&#8217;s omni wheels and keep working on an <a href=\"http:\/\/www.robotplatform.com\/knowledge\/Classification_of_Robots\/Holonomic_and_Non-Holonomic_drive.html\">holonomic<\/a> robot with 3 wheels.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large\" src=\"https:\/\/lh3.googleusercontent.com\/_0mwkQsazsRdwcXdNKUMknPszCLiot8BDRA8HzSp1Pav3ENSljIKScaQztwkiBnhYHxYxrPsDGdNsaBOyLfeSvBZM22zf3f1Iha58sJ74sGvtJxNjeCgFE_6nyvIYoTrVsQ-x0Ivo0uchmWS_6bic9EUuR3d5P6WoE_tQC3EVxvSsmLhhdzjM05hnw8iC_3wb2FTpKDQcpBILAzoy4mXoeQANHrAPd5zQ0sRq2YljzqkFW-K48lPPIUHTy1otqb4uiP0lplfBvqrIpuF9HFk7XXhAcQCOi-lgvDRf96Ye3jXcnjZuhqRVeuLQEdrKNPlNqb5z-_LCb0U4KSsejEGvPAn4ZhIXTD4bBBGS4V4a7yVPl0JQZ0logQIA0rrgAS6duJm65qXUrQipV0KItXwuy5nJptqZrPTtn3wEpFLQGVAwhct46TTFWk2FTkRN-p0u2do8P16bMBPpRY7ZbHVPO_yU9Z3X88YOOOXfHNSyoT_iJMqSmXUdy70vK-o9PmMM0xoX1KRnsUvotYNEV8-43DT6WfX3ErMMRKMoLeOHBOHqAM-BFWBWwj3cp3VPaGoAkDO0SAwjWeSL7353UUn0nfRSAlxrwZK17nh78p3Vz9ADxbuTi-yKX3fYvhCEKjPsTSMRZrrOKjGbFKe_qj2PRgHbORzjCsfL_qWIvXIPg=w1603-h900-no\" width=\"1603\" height=\"900\" \/><\/p>\n<p>Why 3 wheels?<\/p>\n<p>At first I only had NEXO parts to build 3 wheels but I enjoyed the experience &#8211; my first RC experiments seemed like lobsters. Controlling the motion is not easy but I found a <a href=\"http:\/\/thetechnicgear.com\/2014\/04\/howto-build-3-wheels-holonomic-robot-using-lego\/\">very good post from Miguel from The Technic Gear\u00a0<\/a> so it was easy to derive my own equations. But Power Functions motors don&#8217;t allow precise control of speed so I could not make the robot move in some directions. I needed regulated motors like those used with MINDSTORMS EV3.<\/p>\n<p>So after assembling three <a href=\"http:\/\/www.isogawastudio.co.jp\/legostudio\/modelgallery_model\/a065.html\">Isogawa&#8217;s omniwheels<\/a> and making a frame that assured the wheel doesn&#8217;t separate from the motor it was just a matter of making a triangled frame to join all 3 motors and sustain the EV3:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large\" src=\"https:\/\/lh3.googleusercontent.com\/Q45kG1O6qkNNaWzBxuyaU2dgEFd4fRv5FZp3mgETYVhOuaTwGLLlPs3a20nyKNbaKD1EgTSNJwxSkfCgkT5AGLvGds45MOBsDeccrYWv1BDFKA0EFA6t8DLhqCHp7B-QheUe59eNxnAIA8Y2pwUKQQYCcaruLPv2l0cJWhgRjzsSC7610cIHO_QsxRD2N4TY1WaE-F3jAm9mk95jQ2LAgaZO7VeMedutF3GSqNpBWoiuWjx0LjlUPO8Qe9SAuclLcp-lagRRXVd9edwaEP_ys8f-EUR0KbiQ0JwKoMAKC7vFN74G9VqRE9k0tn8r_VqghLOLoNMpXo39GV34jn_zRFq3XKx1cNCh3rGss4DNjCAHH6B4r9gQ1zpVuhkpKrVDlQCRsXtvHbDy39or5xpeJbFWecnWusFOECIuMF3eSG12vDWiqjgJB25CFjfRSnGA9_jzQmLjQETh8X6Sl0fuKsSAxpDEaU_ih09TCZxkl6p_-ngQalKZs7pW_-V21tRB4NMzlk2hJx3uU2xCOl_puX1d4zNTzKsP6WsLju-v2ZXEUrpIL8nQdaQugAKQvbkClkxPn2qp2PVB9eKJFI3-fK95awk2Ce5sWzWIccls2zK03Gmz1R5TnlKUd7vsgC9fr0CcVu9qwu428yZNf7uqLVe758aTbU7rMSYT2xNpkg=w1603-h900-no\" width=\"1603\" height=\"900\" \/><\/p>\n<p>First tests with regulated motor control seem promising: Triplex is fast enough and doesn&#8217;t fall apart.\u00a0 It drifts a bit so I&#8217;ll probably use a gyro sensor or a compass to correct it.<\/p>\n<p>In this demo video I show Triplex being wireless controlled from my laptop keyboard through an SSH session. It just walks &#8220;forward&#8221; or &#8220;backward&#8221; (only two motors are used, running at the same speed in opposite directions) or rotates &#8220;left&#8221; or &#8220;right&#8221; (all motors are used, running at the same speed and the same direction).<\/p>\n<div class=\"jetpack-video-wrapper\"><iframe loading=\"lazy\" title=\"Triplex v0.3 - Remote Control from laptop\" width=\"840\" height=\"473\" src=\"https:\/\/www.youtube.com\/embed\/HKXMQ_zixY0?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/div>\n<p>For the code used in this demo I copied a block of code from Nigel Ward&#8217;s <a href=\"https:\/\/sites.google.com\/site\/ev3python\/learn_ev3_python\/keyboard-control\">EV3 Python<\/a> site that solved a problem I&#8217;ve been having for a long time: how do I use Python to read the keyboard without waiting for ENTER and without installing pygame or other complex\/heavy library?<\/p>\n<pre>#!\/usr\/bin\/env python3\r\n\r\n# shameless based on\r\n# https:\/\/sites.google.com\/site\/ev3python\/learn_ev3_python\/keyboard-control\r\n#\r\n\r\nimport termios, tty, sys\r\nfrom ev3dev.ev3 import *\r\n\r\nTIME_ON = 250\r\n\r\nmotor_A = MediumMotor('outA')\r\nmotor_B = MediumMotor('outB')\r\nmotor_C = MediumMotor('outC')\r\n\r\n#==============================================\r\n\r\ndef getch():\r\n\u00a0\u00a0\u00a0 fd = sys.stdin.fileno()\r\n\u00a0\u00a0\u00a0 old_settings = termios.tcgetattr(fd)\r\n\u00a0\u00a0\u00a0 tty.setcbreak(fd)\r\n\u00a0\u00a0\u00a0 ch = sys.stdin.read(1)\r\n\u00a0\u00a0\u00a0 termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 return ch\r\n\r\n#==============================================\r\n\r\ndef forward():\r\n\u00a0\u00a0\u00a0 motor_A.run_timed(speed_sp=-1200, time_sp=TIME_ON)\r\n\u00a0\u00a0\u00a0 motor_C.run_timed(speed_sp=1200, time_sp=TIME_ON)\r\n\r\n#==============================================\r\n\r\ndef backward():\r\n\u00a0\u00a0\u00a0 motor_A.run_timed(speed_sp=1200, time_sp=TIME_ON)\r\n\u00a0\u00a0\u00a0 motor_C.run_timed(speed_sp=-1200, time_sp=TIME_ON)\r\n\r\n#==============================================\r\n\r\ndef turn_left():\r\n\u00a0\u00a0\u00a0 motor_A.run_timed(speed_sp=1200, time_sp=TIME_ON)\r\n\u00a0\u00a0\u00a0 motor_B.run_timed(speed_sp=1200, time_sp=TIME_ON)\r\n\u00a0\u00a0\u00a0 motor_C.run_timed(speed_sp=1200, time_sp=TIME_ON)\r\n\r\n#==============================================\r\n\r\ndef turn_right():\r\n\u00a0\u00a0\u00a0 motor_A.run_timed(speed_sp=-1200, time_sp=TIME_ON)\r\n\u00a0\u00a0\u00a0 motor_B.run_timed(speed_sp=-1200, time_sp=TIME_ON)\r\n\u00a0\u00a0\u00a0 motor_C.run_timed(speed_sp=-1200, time_sp=TIME_ON)\r\n\r\n#==============================================\r\n\r\nprint(\"Running\")\r\nwhile True:\r\n\u00a0\u00a0 k = getch()\r\n\u00a0\u00a0 print(k)\r\n\u00a0\u00a0 if k == 'a':\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 forward()\r\n\u00a0\u00a0 if k == 'z':\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 backward()\r\n\u00a0\u00a0 if k == 'o':\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 turn_left()\r\n\u00a0\u00a0 if k == 'p':\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 turn_right()\r\n\u00a0\u00a0 if k == ' ':\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 stop()\r\n\u00a0\u00a0 if k == 'q':\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 exit()\r\n\r\n<\/pre>\n<p>Thanks for sharing Nigel!<\/p>\n<p>Now let&#8217;s learn a bit of math with Python.<\/p>\n<p>For those who might interest, I also have some photos with the <a href=\"https:\/\/goo.gl\/photos\/fPLcX85WjdcjLCKD7\">evolution of the project<\/a>.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"seriesmeta\">This post is part 1  of 3 of \u00a0<a href=\"https:\/\/ofalcao.pt\/blog\/series\/triplex\" class=\"series-303\" title=\"Triplex\">Triplex<\/a><\/div><p>A few months ago, trying to find an use for a new LEGO brick found in NEXO Knights sets, I made my first omni wheel. It worked but it was to fragile to be used in a robot so I decided to copy one of Isogawa&#8217;s omni wheels and keep working on an holonomic robot &hellip; <a href=\"https:\/\/ofalcao.pt\/blog\/2017\/triplex-an-holonomic-robot\" class=\"more-link\">Continuar a ler<span class=\"screen-reader-text\"> &#8220;Triplex &#8211; an holonomic robot&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[157,13,18,154,158,19,98],"tags":[294,293],"series":[303],"class_list":["post-1062","post","type-post","status-publish","format-standard","hentry","category-ev3dev-en","category-ev3dev","category-lego","category-lego-en","category-lego-mindstorms-en","category-lego-mindstorms","category-python","tag-holonomic","tag-omni-wheel","series-triplex"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2Mhyv-h8","_links":{"self":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/posts\/1062","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/comments?post=1062"}],"version-history":[{"count":0,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/posts\/1062\/revisions"}],"wp:attachment":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/media?parent=1062"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/categories?post=1062"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/tags?post=1062"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/series?post=1062"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}