روباتیک

رباتی طراحی کنید که بدون انحراف از مسیر حرکت می‌کند

making-robot-straight

اگر شما ربات سیاری را طراحی می‌کنید یا پروژه ربات در دست دارید که انجام وظیفه‌ای را بر عهده دارد مانند ربات مسیریاب، از برخی جهات ممکن است با این مسئله روبه‌رو شوید که بخواهید ربات خود را به سمت یک مکان به خصوص حرکت دهید. در مسابقات رباتیک مربوط به ربات‌های آتش‌نشان، ربات شما باید توانایی مسیریابی در یک مارپیچ مشخص‌شده را داشته باشد. بخش زیادی از زمان تیم ها صرف این مسئله می شود که بتوانند ربات را به شکلی برنامه‌نویسی کننند تا بتواند از عهده‌ی یک وظیفه‌ی ظاهراً ساده، یعنی حرکت در مسیر مستقیم، بر آید. ساده به نظر می‌رسد، شما اینطور فکر نمی‌کنید؟ برای یک ربات دیفرانسیلی با دو چرخ، کافی است تا گشتاور یکسانی را به هر کدام از چرخ‌ها منتقل کنید.

اما این روش واضح، آن اندازه که به نظر می‌رسد، به خوبی عمل نمی‌کند. ربات من زمانی که باید دیواره‌ها را تشخیص دهد، به لطف استفاده از سنسورها، عملکرد خوبی دارد که بخش مهمی از یک مسابقه‌ی مارپیچ محسوب می‌شود. اگر چه در نهایت، مسائلی وجود دارند که باید خودش به تنهایی با آن‌ها کنار بیاید و اینجاست که این ربات دو مشکل بزرگ دارد:

  • لغزش آن همچنان قابل‌ملاحظه است،

  • بر روی سطوح هموار، ممکن است اندکی جست و خیز کند تا اینکه متوقف شود و در نتیجه موقعیت نهایی ربات غیرقابل پیش‌بینی است.

این یک مشکل دیوانه‌کننده بود. بعضی اوقات ربات به سمتی که می‌خواهم حرکت می‌کند و گاهی اوقات نه! برای حل این مشکل کارهای مختلفی انجام دادم. من یک ضریب تصحیح (Fudge Factor) را به ولتاژ موتور اضافه کردم که در نتیجه‌ی آن قسمت چپ ربات اندکی سریع‌تر حرکت می‌کرد. من حتی از یک کنترل‌کننده‌ی پی آی دی (PID Controller) برای حذف تیک‌های رمزگذار (ناشی از مسافت پیموده شده) در سمت راست و چپ استفاده کردم. ولتاژ موتور و به تبع آن، سرعت را کاهش دادم تا لغزش به حداقل برسد. اما نمی‌توانم خیلی آرام حرکت کنم چرا که قرار است بر روی موکت از آن استفاده شود و روبات در صورتی که گشتاور آن خیلی کم باشد، قادر به حرکت بر روی سطوحی مثل موکت نخواهد بود. خوشبختانه می‌توانم موتورهای ربات را متوقف کنم؛ در غیر اینصورت موقعیت ربات در یک ساعت بعدی اصلاً قابل پیش‌بینی نبود. روی هم رفته، موقعیتی نبود که بتوانم به آن اعتماد کنم و می‌دانستم که اگر با این ربات وارد مسابقات بشوم، احتمال پیروزی من بسیار پایین است. (که در نهایت هم این اتفاق افتاد و ربات ما در آخرین دقیقه به سبب یک اشکال نرم‌افزاری نامربوط کارش را در مسابقات به پایان رساند.)

یک مرحله به‌روزرسانی موتورها بود که شامل استفاده از اینکدر بهتری هم می‌شد. اینکدر (Encoder) ابزاری است که میزان چرخش محور موتور و در نتیجه اندازه‌ی گردش چرخ‌ها را به شما نشان می‌دهد. اگر از لغزش چرخ‌ها صرفنظر شود، این ابزار در نهایت به شما مسافت پیموده‌شده را می‌دهد. اگر چه، همچنان مشکل اصلی در جای خود باقی است و روبات همچنان می‌لغزد.

وقت آن است که از نرم‌افزار بهتری استفاده کنیم! کد اصلی روبات من تا حدی بر پایه‌ی کد مایک فرگوسن (Mike Ferguson) برای ربات کریتر (Crater) بود که در مسابقات ترینیتی (Tinity) به موفقیت رسید. ربات او از قدرت پردازش به مراتب کمتری برخوردار بود، او از پردازنده‌ی اتمل ۱۶۸ (Atmel 168) استفاده می‌کرد در حالی که ربات من دارای پردازنده‌ی مگا (Mega) بود و همچنین آن ربات هیچ نوعی از کنترل‌کننده‌ی PID را استفاده نمی‌کرد و البته در یک نسخه‌ی جذاب‌تر از کریتر، او همچنان به مشکل هدایت ربات در مسیر مستقیم اشاره کرد. من فکر می‌کنم که جواب این سوال در اینجا نهفته است.

به عنوان یک خوش‌شانسی، یکی از آموزش‌های سایت Coursera با موضوع کنترل ربات‌های سیار شروع شد و یکی از مثال‌های آن به من ایده‌ی این راه‌حل را داد. من قصد دارم تا آن را در اینجا به طور خلاصه بیان کنم، البته به همراه اندکی جزئیات تکمیلی برای همه‌ی کسانی که از ربات‌های دیفرانسیلی استفاده می‌کنند. من از اسلایدهای این آموزش استفاده نخواهم کرد چرا که از نشانه‌گذاری‌های به شدت پیچیده‌ای در آن‌ها استفاده شده است (مثلا نماد v در یک صفحه، گاهی به معنای سرعت زاویه‌ای و گاهی به معنای سرعت خطی به کار رفته است!). به جای آن من این آموزش سینماتیک ربات‌های دیفرانسیلی را پیشنهاد می‌کنم. در نهایت از این آموزش می‌توان این معادلات را استنباط کرد:

making-robot-straight1

که در آن‌ها sr و sl به ترتیب بیانگر جابه‌جایی (یا همان مسافت پیموده‌شده) برای چرخ‌های راست و چپ هستند و b فاصله‌ی بین چرخ‌ها (از مرکز به مرکز در راستای طول محور چرخ‌ها) است و تتا(θ) زاویه‌ی سر ربات نسبت به محور x ها است.

با داشتن این معادلات، ما می‌توانیم برنامه‌ای را برای کنترل‌کننده‌ی PID و با هدف کنترل زاویه‌ی تتا یا همان سر ربات، بازنویسی کنیم. در مورد شخصی خودم، من عبارت تناسبی را به کار بردم و یک نمونه‌ی منطقی سرعت را براساس تیک‌های دوره‌ای رمزگذار (Encoder) انتخاب کردم. تقریباً به طور مداوم، ربات می‌توانست در مسیر راست حرکت کند و این مثل یک معجزه بود!

به کمک این روش، من از PID برای سرعت خطی کلی استفاده کردم که با استفاده از آن ربات من می‌تواند با یک سرعت متوسط یکسان بر روی تمام سطوح حرکت کند. ربات بر روی سطوح سخت به نرمی حرکت می‌کند و زمانی که به سطوحی مثل موکت می‌رسد، اندکی گشتاور خود را بالا می‌برد تا سرعت خود را حفظ کند.

به خاطر مایک فرگوسن و همه‌ی کسانی که کدهای خود را در بین دیگران به اشتراک گذاشتند، من هم قدم در این راه گذاشتم و کدهای خودم را در کتابخانه‌ی GitHub قرار دادم تا دیگران هم بتوانند از آن استفاده کنند. البته من هنوز لینک مستقیم را در اینجا قرار نمی‌دهم چرا که این کدها همچنان به شکل ملایمی در حال توسعه هستند …

واقعیت فیزیکی مزاحم

بعد از اینکه به خاطر این قابلیت‌های جدید برای چند روز خوشحال بودیم، به طور اتفاقی ربات دیگر به شکل مطمئنی حرکت نمی‌کرد. متاسفانه این اتفاق در زمان بدی رخ داد. در ابتدا تصور کردم که با یک اشکال نرم‌افزاری روبه‌رو هستم اما در نهایت متوجه شدم که مشکل به موتورهای فال هابر (Faulhaber) برمی‌گردد. این موتورها از گیربکس‌های قائمه استفاده می‌کنند و تعدادی از پیچ‌های آن در طی این مدت شل شده بودند؛ در نتیجه محور اصلی موتور حرکت می‌کرد اما این گشتاور به چرخ‌ها منتقل نمی‌شد یا حداقل بعضی مواقع به این شکل بود. وقتی پیچ‌ها را محکم کردم، رفتار روبات دوباره به حالت خوب اولیه برگشت. این مسئله یکی از معایب رمزگذارهای یکپارچه (Integrated Encoder) را نمایان می‌کرد. اگر چه من به شخصه به این رمزگذارها علاقه‌ی خاصی دارم اما کسانی که در این زمینه کار می‌کنند، به چرخ‌ها نگاه می‌کنند نه محور موتور و چرخش چرخ‌ها تمام چیزی است که ما باید در عمل برای آن اهمیت قائل باشیم.

گیربکس‌ها به شکل موثری محور موتور را گسترش می‌دهند، اما در عوض قابلیت ایجاد مشکلات مکانیکی از جمله درگیری دنده‌ها در آن‌ها وجود دارد و همین امر آن‌ها را بی‌استفاده می‌کند. من آن‌ها را از یک جفت موتور حذف کردم و تنها ۳ میلی‌متر طول محور موتور برایم باقی ماند. البته چند تا توپی چرخ استاندارد پولولو (Polulu Universal Hub) خیلی باریک پیدا کردم که با مدل من سازگار بودند و سوراخ‌هایی را در یک جفت چرخ لایت-فلایت (Lite-Flite Wheel) ایجاد کردم تا بتوانم آن‌ها را به هم وصل کنم. محصول نهایی چیزی شبیه به عکس‌های زیر است:

making-robot-straight2

making-robot-straight3

اگر چه این چرخ‌ها چند تست ساده را با موفقیت پشت سر گذاشتند اما هنوز به پایه‌ی اصلی متصل نشدند. پایه‌ی اصلی هم برای اتصال چرخ‌ها نیاز به یکسری تغییرات دارد. برای پلتفرم کار یکی از مدل‌های موجود در Budget Robotics را استفاده کردم که چرخ‌ها را در وسط قرار داده بود و در نتیجه از دو کستر (Caster) در قسمت عقب و جلو استفاده می‌کرد. این پلتفرم در حقیقت برای روبات‌های لغزان با حرکات محدود طراحی شده بود. بعد از تجربه‌ی ربات بر روی چند نمونه موکت مجدداً به این اصل رسیدم که «سه نقطه یک صفحه را تشکیل می‌دهند» و بهتر است که تنها از یک کستر استفاده کنم چرا که در غیر اینصورت ممکن است تا یک چرخ به راحتی از روز سطح بلند شود و در نتیجه کنترل و پایداری روبات به طور کامل به هم بخورد؛ روبات اینگونه تصور می‌کند که آن قسمت همچنان در حال حرکت است در حالی که اینگونه نیست و اودومتری (Odometry) به طور کامل به اشتباه می‌افتد. به همین خاطر من قصد دارم تا چرخ‌ها به قسمت عقب روبات متصل کنم و برای این کار مجبورم تا قسمتی از بدنه‌ی اصلی را جدا کنم.

قدم‌های بعدی

اگر چه سیستم مسیریابی ربات تا حد زیادی بهبود پیدا کرده است اما من قصد دارم تا برنامه‌های خودم را بر روی احتمالات پایه‌گذاری کنم. همچنان سطوح موکتی وجود دارند که می‌توانند نگران‌کننده باشند و اساسی‌تر از آن، یک روبات باید از سنسورهای خود برای سازگاری با محیط اطراف استفاده کند. ربات فایرچیتا (FireCheetah) سنسورهای نسبتاً کمی دارد که اگر به درستی استفاده شوند، می‌توانند رفتار بازیابی خوبی از خود به نمایش بگذارند. من این روند را ادامه می‌دهد و ثابت می‌کنم که این سیستم مسیریابی «عادی» می‌تواند در مارپیچ‌ها عمل کند، تا آن زمان می‌توانیم با این ربات خوش بگذرانم و آن را در گوشه‌ها قرار دهم و ببینم که چگونه مسیر حرکت خود را دوباره پیدا می‌کند.س

خوب(7)بد(0)
همچنین ممکن است بپسندید
ربات مسیریاب با کنترلر PID
چیدمان سنسور ربات مسیریاب

دیدگاه خود را بیان فرمائید

نام شما *
وبسایت شما *

دیدگاه شما *

شما می‌توانید از این دستورات HTML استفاده کنید: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>