کنترل PID با TurtleSim

مخزن GitLab پروژه

چکیده

Move Turtle یک اسکریپت سادهٔ پایتون ROS است که لاک‌پشت را در TurtleSim مربوط به ROS به مختصات مشخص (نقاط) حرکت می‌دهد. این پروژه به‌عنوان یک پروژهٔ کلاسی برای CSCI473 در Colorado School of Mines (CSOM) آغاز شد و بعدها به پروژه‌ای تبدیل شد که از آن برای کمک به یادگیری این‌که چگونه سیستم‌های حلقه‌بسته می‌توانند ساخته شوند استفاده کردم؛ دانشی که بعدها برای کمک به کارم در آزمایشگاه Human Center Robotics (HCR) در CSOM از آن بهره بردم.

زمینه

برای کمی زمینه، ROS مخفف Robot Operating Systems است. ROS یک میان‌افزار رباتیک متن‌باز است که معمولاً همراه با سیستم‌عامل Ubuntu استفاده می‌شود و برای مدیریت بهتر مؤلفه‌ها/خوشه‌های نرم‌افزاری یک سامانهٔ رباتیک به کار می‌رود. شما می‌توانید دربارهٔ نحوهٔ استفاده از ROS از طریق ویکی رسمی ROS بیشتر بیاموزید. کدی که در ROS می‌نویسید یا به زبان C++ است یا Python.

TurtleSim یک شبیه‌ساز سادهٔ ربات دوبعدی است که به‌عنوان مقدمه‌ای بر ROS و بسته‌های ROS برای کاربران جدید ROS استفاده می‌شود. کاری که TurtleSim انجام می‌دهد فقط باز کردن یک نمایشگر سادهٔ دوبعدی با یک لاک‌پشت است. آن لاک‌پشت به‌عنوان «ربات» عمل می‌کند و شما می‌توانید برای حرکت دادن و/یا چرخاندن آن «ربات» پیام ارسال کنید. همچنین هنگام حرکت، TurtleSim برای شبیه‌سازی سادهٔ فیزیک دنیای واقعی مقداری خطای تصادفی تولید می‌کند.

حال که می‌دانیم ROS و TurtleSim چیست، چرا از آن‌ها استفاده می‌کردم؟ خب، در بهار 2020 من در درسی به نام «Human Centered Robotics» در Colorado School of Mines به‌عنوان بخشی از واحدهای درسی کارشناسی علوم کامپیوتر خود شرکت می‌کردم. این درس را دکتر Hao Zhang تدریس می‌کرد. این درس از سه پروژه تشکیل می‌شد و پروژهٔ اول شامل راه‌اندازی ROS، یادگیری نحوهٔ استفاده از ROS، و پیاده‌سازی یک الگوریتم حلقه‌باز یا حلقه‌بسته بود که باعث می‌شد لاک‌پشت در TurtleSim یک M رسم کند. توضیح اصلی پروژه را می‌توان اینجا مشاهده کرد.

وقتی این درس را می‌گذراندم، این پروژه را با پیاده‌سازی یک الگوریتم حلقه‌باز انجام دادم. این راه‌حل کار می‌کرد، اما واقعاً افتضاح بود و یک A ترسیم می‌کرد که «به‌اندازهٔ کافی خوب» بود، اما اصلاً به «عالی» نزدیک نبود. بعد از ارسال پروژه در حدود اواسط فوریهٔ 2020، تا حدود یک سال بعد، یعنی حوالی فوریهٔ 2021، آن را فراموش کردم.

چالش

در فوریهٔ 2021، به‌عنوان دستیار پژوهشی در آزمایشگاه Human Centered Robotics (HCR) در Colorado School of Mines استخدام شدم، جایی که تحت نظر دکتر Hao Zhang کار می‌کردم. هدف آزمایشگاه انجام پژوهش دربارهٔ «خودمختاری مشارکتیِ مادام‌العمر، با هدف توانمندسازی ربات‌ها برای کار کردن و سازگار شدن در بازه‌های زمانی طولانی» است. تا تاریخ 9-1-2022 (1 سپتامبر 2022)، آزمایشگاه از Colorado School of Mines به University of Massachusetts Amherst منتقل شده است. اما زمانی که من آنجا کار می‌کردم، هنوز در کلرادو مستقر بودند.

در آزمایشگاه HCR، وظیفه داشتم روی پروژهٔ Triton کار کنم. پروژهٔ Triton از چندین، ده‌ها، ربات به نام Triton تشکیل شده بود. Tritonها ربات‌های زمینی مثلثی با چرخ omni بودند که به این شکل بودند:

در کنار Tritonها، هشت دوربین IR از OptiTrack که به‌صورت «چینش هشت‌ضلعی» چند فوت بالاتر از زمین قرار گرفته بودند. با استفاده از آن دوربین‌ها، نرم‌افزار Motive شرکت Optitrack، یک رایانهٔ دارای Windows 10، و ROS؛ فضایی به ابعاد 2 متر در 2 متر در 2 متر (x, y, z) ایجاد می‌شود که در آن می‌توان موقعیت دقیق دنیای واقعیِ اشیاء دارای نشانگرهای موشن کپچر را تعیین کرد.

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

پژوهش

در جریان پژوهش خود، این ویدیوی عالی از AerospaceControlsLab را پیدا کردم:

در این ویدیو، ایدهٔ یک سیستم PID به من نشان داده و توضیح داده شد. یک سیستم PID یک سیستم حلقه‌بسته، کنترل‌حلقه، است که بر اساس داده‌های دنیای واقعی خروجی(های) مشخصی تولید می‌کند. به‌طور ساده، این یک سیستم بازخورد است که خروجی خود را بر اساس تفاوت بین مقدار مطلوب و مقدار اندازه‌گیری‌شده تنظیم می‌کند. این فرمولِ یک کنترل‌کنندهٔ PID است:

$$ u(t) = K_p e(t) + K_i \int e(t) dt + K_d \frac{de(t)}{dt} $$

  • $u(t)$ سیگنال کنترلی است.
  • $K_p$، $K_i$، $K_d$ به‌ترتیب بهره‌های تناسبی، انتگرالی و مشتقی هستند.
  • $e(t)$ سیگنال خطا است (تفاوت بین خروجی مطلوب و خروجی واقعی).
  • $\int e(t) dt$ انتگرال خطا در طول زمان است.
  • $\frac{de(t)}{dt}$ مشتق خطاست.

برای یادگیری بیشتر دربارهٔ آن، ویدیوی AerospaceControlsLab یا این مقالهٔ ویکی‌پدیا شگفت‌انگیز را که فرمول از آن است بررسی کنید.

پس از انجام پژوهش‌هایم و نیز دریافت کمی کمک از دوستان و استادان باهوشم، به این نتیجه رسیدم که استفاده از یک کنترل‌کنندهٔ تناسبی، یعنی کنترل‌کنندهٔ P، برای کمک به Triton در رسیدن به یک مختصات مشخص بهترین گزینه خواهد بود.

چون Triton یک ربات زمینی است، فقط لازم است دربارهٔ مختصات X و Y نگران باشم. با دانستن این موضوع، سپس باید تعیین می‌کردم چه مقادیر مطلوب و چه مقادیر اندازه‌گیری‌شده‌ای باید در کنترل‌کننده(های) P اندازه‌گیری و پردازش شوند. در پژوهش خود، این پست فوق‌العاده را در ویکی ROS با عنوان Go to Goal پیدا کردم که بر خطاهای زیر تمرکز داشت:

  • خطای فاصله: تفاوت در فاصله بین موقعیت مطلوب (X, Y) و موقعیت فعلی (X, Y).
  • خطای تتا: تفاوت بین جهت‌گیری مطلوب و جهت‌گیری فعلی.

راه‌حل پیشنهادی

با دانستن همهٔ این‌ها، راه‌حل برای واداشتن Triton به حرکت به سمت یک مختصات مشخص در دنیای واقعی این است که از یک کنترل‌کنندهٔ تناسبی برای خطای فاصله و خطای تتا‌ی Triton نسبت به مختصات هدف و مختصات فعلی Triton استفاده شود. اما پیش از پیاده‌سازی این در یک سامانهٔ فیزیکی، می‌خواستم ایده را در یک شبیه‌سازی آزمایش کنم و در آن زمان، فکر می‌کردم استفاده از TurtleSim به‌عنوان شبیه‌سازی بهترین انتخاب است.

آزمودن در شبیه‌سازی

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

پس از به‌روزرسانی کد قدیمی از ROS Melodic به ROS Noetic و با کمی پالایش تکراری، راه‌حل پیشنهادی را در TurtleSim به کار انداختم. نمایش‌های عملکرد آن، همراه با چند مسیر جالب مختصات هدف، در انتهای این پست وبلاگ یافت می‌شوند. کد همهٔ این‌ها را می‌توان اینجا مشاهده کرد.

نتیجه‌گیری

خلاصه اینکه، از خلال این پروژه، لاک‌پشت TurtleSim با استفاده از سیستم حلقه‌بسته به‌طور مؤثر به مختصات تنظیم‌شده حرکت می‌کند و به‌مراتب بهتر از سیستم حلقه‌باز اولیهٔ من در سال 2020 عمل می‌کند. پس از آزمون موفقیت‌آمیز، این راه‌حل را با ربات‌های Triton پیاده‌سازی کردم. اما نویز دنیای واقعی مسائل پیش‌بینی‌نشده‌ای ایجاد کرد که نیازمند هفته‌ها اشکال‌زدایی و آزمون‌های دنیای واقعی بود. پس از آن هفته‌ها، در نهایت توانستم Triton را با استفادهٔ نهایی از همان راه‌حلی که در TurtleSim آزموده بودم به مختصات مشخص دنیای واقعی برسانم. در اینجا یک دموی حرکت Triton به سمت مختصات مشخص دنیای واقعی با استفاده از روشی که در TurtleSim آزموده شده است آمده:

با نگاه به گذشته، ای کاش از شبیه‌سازی‌ای استفاده می‌کردم که فیزیک دنیای واقعی را بهتر شبیه‌سازی کند. TurtleSim برای یادگیری عالی است، اما برای آزمودن ایده‌های رباتیک دنیای واقعی عالی نیست. در آن زمان فکر می‌کردم برای مورد استفادهٔ سادهٔ من به‌اندازهٔ کافی خوب باشد، اما بعداً ثابت شد که این‌طور نیست.

هدف اصلی این پست وبلاگ این بود که ایجاد یک سیستم حلقه‌بسته را تشریح کند که به لاک‌پشت در TurtleSim، و سپس به ربات‌های Triton، امکان می‌دهد تا با دقت به موقعیت‌های هدف مشخص (X, Y) ناوبری کنند. من معتقدم این هدف محقق شد، اما شاید برای کار من در آزمایشگاه HCR هم کمی جلب توجه کرده باشد. با دانستن این موضوع، برنامه‌هایی برای نوشتن پست‌های وبلاگ بیشتر دربارهٔ تجربهٔ کاری‌ام در آزمایشگاه HCR دارم…

دموهای حرکت لاک‌پشت (TurtleSim)

این ویدیو شامل دموهای زیر است:

  • Cayley Nodal: یک طراحی سادهٔ Cayley Nodal
  • Circles: یک طراحی شبیه تار عنکبوت
  • Inner Circles: یک طراحی «دایره‌ها درون دایره‌ها»
  • M: یک طراحی بسیار سادهٔ M