مسیر یادگیری ROS 2  ·  کتاب آموزشی تصویری

فصل سیزدهم: MoveIt 2 — وقتی ARCHO دست بلند می‌کند

از دنبال‌کردن یک نقطه تا برنامه‌ریزی حرکت یک بازوی چندمحوره
پیش‌نیاز: فصل ۴ (URDF/Xacro)، فصل ۵ (TF2)
پروژه پیوسته: ربات ARCHO با بازوی برداشت
ابزار: MoveIt 2 و OMPL
زمان مطالعه: ۱۴۰ تا ۱۶۰ دقیقه
در این فصل چه می‌خوانیم ۱۳.۱MoveIt: مغز بازوی رباتیک ۱۳.۲Forward Kinematics: اگر زاویه مفصل‌ها را بدانم ۱۳.۳Inverse Kinematics: اگر هدف را بدانم ۱۳.۴Workspace، Singularity و جواب‌های چندگانه ۱۳.۵Planning Scene: حافظه دیجیتالی دنیای ARCHO ۱۳.۶Collision Detection: نگهبان قبل از هر حرکت ۱۳.۷Configuration Space: جایی که MoveIt واقعاً جستجو می‌کند ۱۳.۸OMPL: RRT، RRTConnect و PRM ۱۳.۹از Path تا Trajectory اجراشدنی ۱۳.۱۰جمع‌بندی، واژه‌نامه و تمرین‌ها

۱۳.۱MoveIt: مغز بازوی رباتیک

فرض کن روی نسخه‌ای از ARCHO کار می‌کنی که علاوه‌بر چرخ‌ها، یک بازوی برداشت هم دارد — برای برداشتن جعبه از قفسه. تا الان با Nav2 دیدیم چطور ARCHO در فضا حرکت می‌کند. اما وقتی نوبت حرکت‌دادن بازو می‌رسد، مسئله کاملاً فرق دارد: اگر Nav2 مغز حرکت ربات متحرک است، MoveIt 2 مغز بازوی رباتیک است.

🧠 چرا نمی‌توان فقط گفت «برو آنجا»

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

۱۳.۲Forward Kinematics: اگر زاویه مفصل‌ها را بدانم

فرض کن این بازو را داری:

Base → Joint1 → Joint2 → Joint3 → Gripper

حالا یک سؤال ساده: اگر زاویه هر سه مفصل را بدانم، نوک بازو (Gripper) دقیقاً کجای فضا قرار دارد؟

flowchart LR A["Joint Angles
Joint1=20°, Joint2=35°, Joint3=-15°"] --> B["Forward Kinematics"] --> C["End Effector Position
X, Y, Z"] style B fill:#eef0ff,stroke:#3d4bf5
🧠 تشبیه دست خودت

اگر زاویه شانه، آرنج و مچ دستت را بدانم، می‌توانم محل دقیق نوک انگشتت را حساب کنم — این دقیقاً همان FK است. این محاسبه ساده است چون فقط «جلو می‌رویم»: زاویه موتور → زاویه لینک → موقعیت لینک → نوک بازو. همیشه دقیقاً یک جواب وجود دارد.

FK همان‌جایی است که TF2 (فصل ۵) واقعاً از آن استفاده می‌کند: وقتی TF می‌گوید «جوینت‌ها این زاویه‌ها را دارند»، این FK است که موقعیت واقعی gripper_link یا camera_link را در فضا محاسبه می‌کند. RViz، Gazebo و Collision Detection همگی دائم از FK استفاده می‌کنند.

۱۳.۳Inverse Kinematics: اگر هدف را بدانم

حالا سؤال را برعکس کن: اگر بدانم نوک بازو باید کجا باشد (مثلاً X=0.50، Y=0.20، Z=0.80)، هر مفصل باید چند درجه بچرخد؟

flowchart LR A["Target Pose
X, Y, Z"] --> B["Inverse Kinematics"] --> C["Joint Angles"] style B fill:#f4effe,stroke:#8b5cf6
🔧 چرا IK سخت‌تر از FK است

وقتی می‌گویی «لیوان روی میز را بردار»، مغزت خودش زاویه شانه، آرنج و مچ را محاسبه می‌کند — این IK است. اما بر خلاف FK، IK ممکن است چند جواب داشته باشد (مثلاً آرنج بالا یا آرنج پایین، هر دو به هدف می‌رسند)، هیچ جوابی نداشته باشد (هدف خارج از دسترس)، یا حتی بی‌نهایت جواب داشته باشد.

چرا IK از FK مهم‌تر است؟ چون انسان (یا اپراتور خط تولید) همیشه هدف را مشخص می‌کند — «این پیچ را ببند»، نه «Joint1 را ۱۳ درجه بچرخان». MoveIt این ترجمه از هدف به زاویه مفصل‌ها را برای تو انجام می‌دهد.

Forward KinematicsInverse Kinematics
ورودیزاویه مفصل‌هاموقعیت هدف (Pose)
خروجیموقعیت نوک بازوزاویه مفصل‌ها
تعداد جوابهمیشه دقیقاً یکیصفر، یک، چند، یا بی‌نهایت
سختی محاسباتیساده و مستقیممعمولاً نیازمند حل‌کننده عددی
استفاده رایجRViz، TF، Robot State، GazeboMoveIt، Pick & Place، Manipulation

در بازوهای ۶ یا ۷ محوره واقعی، معمولاً فرمول بسته ساده‌ای برای IK وجود ندارد و از حل‌کننده‌های عددی مثل KDL، TRAC-IK یا IKFast استفاده می‌شود که MoveIt می‌تواند هرکدام را به‌عنوان پلاگین به کار ببرد.

⚠️ بزرگ‌ترین اشتباه تازه‌کارها

فکر نکن FK یعنی «حرکت‌دادن بازو» یا IK یعنی «حرکت‌دادن موتور». هیچ‌کدام این کار را نمی‌کنند — این‌ها فقط محاسبه می‌کنند. اجرای واقعی حرکت کار ros2_control و Controllerها (فصل ۸) است.

۱۳.۴Workspace، Singularity و جواب‌های چندگانه

📖 Workspace چیست

Workspace یعنی تمام نقاطی که بازو واقعاً می‌تواند به آن‌ها برسد. اگر هدف بیرون این محدوده باشد، IK پاسخ می‌دهد: Unreachable — یعنی رسیدن اصلاً امکان‌پذیر نیست، صرف‌نظر از این‌که مسیر چقدر باز باشد.

📖 Singularity چیست

وقتی بازو کاملاً کشیده و صاف می‌شود، حرکت در بعضی جهت‌ها ناگهان سخت یا حتی غیرممکن می‌شود — به این وضعیت Singularity می‌گویند. MoveIt سعی می‌کند مسیرهایی که به این وضعیت نزدیک می‌شوند را دور بزند.

حالت IKعلت
چند جواب (مثلاً آرنج بالا/پایین)هندسه بازو اجازه چند وضعیت متفاوت برای رسیدن به یک هدف را می‌دهد
بدون جواب (No IK Solution)هدف خیلی دور، Joint Limit اجازه نمی‌دهد، یا مانعی سر راه است

۱۳.۵Planning Scene: حافظه دیجیتالی دنیای ARCHO

اگر MoveIt فقط IK داشته باشد، ممکن است بهترین جواب ریاضی را انتخاب کند — حتی اگر مسیرش از وسط یک جعبه روی میز عبور کند. سؤال اینجاست: MoveIt از کجا اصلاً می‌فهمد آن جعبه وجود دارد؟

📖 تعریف Planning Scene

Planning Scene یک مدل دیجیتالی کامل از دنیایی است که ARCHO در آن حرکت می‌کند: خود ربات، میز، کف، دیوار، جعبه‌ها، ابزار، انسان، تجهیزات ثابت، قفسه‌ها و نوار نقاله. MoveIt همیشه، قبل از هر حرکت، این دنیا را در حافظه بررسی می‌کند.

🌍 Planning Scene ثابت نیست

فرض کن یک کارگر یک جعبه جدید روی میز کنار ARCHO می‌گذارد. Planning Scene بلافاصله به‌روزرسانی می‌شود و از همان لحظه، مسیرهای جدید MoveIt خودکار آن جعبه را دور می‌زنند — بدون این‌که کسی خط جدیدی کد بنویسد.

Attached Object: وقتی بازو خودش را بزرگ‌تر می‌کند

وقتی ARCHO یک جعبه را برمی‌دارد، از آن لحظه جعبه عملاً جزئی از خود ربات محسوب می‌شود — به این Attached Object می‌گویند. اگر MoveIt این را فراموش کند، ممکن است فکر کند بازو هنوز باریک است، در حالی که با جعبه در دست، عرض واقعی‌اش مثلاً از ۴۰ سانتی‌متر به ۸۰ سانتی‌متر رسیده — و همین باعث برخورد جعبه با دیوار می‌شود، حتی اگر خود بازو کاملاً سالم از کنارش رد شده باشد.

۱۳.۶Collision Detection: نگهبان قبل از هر حرکت

MoveIt قبل از اجرای هر مسیر می‌پرسد: «آیا بازو در هیچ لحظه‌ای از این مسیر به چیزی برخورد می‌کند؟» و این بررسی فقط ابتدا و انتهای مسیر نیست — در صدها یا هزاران نقطه میانی مسیر هم انجام می‌شود. اگر ابتدا و انتها سالم باشند اما وسط مسیر برخورد رخ دهد، آن مسیر رد می‌شود.

نوع Collisionمعنیمثال
Self Collisionربات به خودش برخورد می‌کندGripper در اثر خم‌شدن زیاد آرنج به Upper Arm می‌خورد
World Collisionبرخورد با محیطمیز، دیوار، انسان، جعبه، قفسه
🔧 چرا MoveIt همه Linkها را با هم بررسی نمی‌کند

دو مفصل مجاور مثل Joint1 و Joint2 طبیعتاً همیشه به هم نزدیک‌اند و بررسی مداوم برخوردشان بی‌فایده و کند است. MoveIt یک Self-Collision Matrix می‌سازد که مشخص می‌کند کدام جفت‌ها اصلاً نیاز به بررسی ندارند — و همین محاسبات را به‌طرز چشمگیری سریع‌تر می‌کند.

یادت هست در فصل ۴ گفتیم URDF دو بخش visual و collision دارد؟ MoveIt فقط از بخش collision استفاده می‌کند — یک جعبه ساده به‌جای پیچ، لبه و لوگوی دقیق مدل بصری، چون برای بررسی برخورد کافی و بسیار سریع‌تر است.

Allowed Collision Matrix

گاهی برخورد کاملاً طبیعی و لازم است — مثلاً Gripper باید به جسم برخورد کند تا بتواند آن را بگیرد. MoveIt این استثناها را با یک ماتریس مشخص می‌کند: Gripper ↔ Object → Allowed، اما Gripper ↔ Table → Not Allowed.

Constraints: محدودیت‌های اضافه روی مسیر

نوع Constraintمثال
Orientation Constraintلیوان آب همیشه باید عمودی بماند
Position Constraintبازو فقط داخل یک محدوده مشخص حرکت کند
Joint ConstraintJoint3 هرگز از ۹۰ درجه بیشتر نشود
Workspace Constraintبازو فقط داخل یک حجم مشخص اجازه حرکت دارد

۱۳.۷Configuration Space: جایی که MoveIt واقعاً جستجو می‌کند

فرض کن بازوی ARCHO ۶ مفصل دارد و هر مفصل فقط ۱۰۰ حالت مختلف داشته باشد. اگر MoveIt بخواهد همه ترکیب‌ها را امتحان کند، باید ۱۰۰⁶ یعنی یک تریلیون حالت را بررسی کند — کاملاً غیرممکن.

🧠 شاید مهم‌ترین مفهوم کل Motion Planning

خیلی‌ها فکر می‌کنند MoveIt مسیر را داخل فضای سه‌بعدی اتاق پیدا می‌کند. اشتباه است. MoveIt در واقع داخل Configuration Space (C-Space) — فضای زاویه مفصل‌ها — جستجو می‌کند. اگر ۶ مفصل داشته باشی، هر وضعیت بازو یک نقطه در یک فضای ۶ بعدی است، نه یک نقطه در اتاق.

داخل C-Space، بعضی نقاط Free Space (مجاز و بدون برخورد) هستند و بعضی Collision Space (غیرمجاز چون به میز، دیوار یا خود بازو برخورد دارند). هدف Motion Planner پیدا کردن مسیری از نقطه Start تا نقطه Goal است که کاملاً داخل Free Space باقی بماند.

۱۳.۸OMPL: RRT، RRTConnect و PRM

📖 OMPL چیست

Open Motion Planning Library — MoveIt خودش الگوریتم مسیریابی نمی‌نویسد، بلکه از این کتابخانه متن‌باز استفاده می‌کند. ورودی OMPL: Planning Scene + Robot Model + Goal. خروجی: یک Trajectory.

RRT (Rapidly-exploring Random Tree)

به‌جای بررسی کل فضا، RRT مثل ریشه یک گیاه یک درخت را از نقطه شروع رشد می‌دهد. هر شاخه جدید یک وضعیت تصادفی جدید از بازو است. اگر شاخه‌ای به مانع بخورد، حذف می‌شود و درخت از مسیر دیگری رشد می‌کند. وقتی یک شاخه به Goal برسد، همان شاخه تبدیل به مسیر نهایی می‌شود.

RRTConnect

نسخه بهتر: به‌جای یک درخت، دو درخت هم‌زمان رشد می‌کنند — یکی از Start و یکی از Goal. وقتی این دو درخت به هم برسند، مسیر پیدا شده است. این معمولاً سریع‌ترین Planner موجود در MoveIt است.

PRM (Probabilistic Roadmap)

ابتدا هزاران نقطه تصادفی در C-Space تولید و به هم وصل می‌شوند — مثل ساختن یک نقشه جاده. بعد فقط مسیر مناسب روی همان جاده انتخاب می‌شود.

RRT / RRTConnectPRM
روشهر بار از صفر شروع می‌کنداول یک «جاده» ثابت می‌سازد، بعد از همان استفاده می‌کند
مناسب برایمحیط دائماً در حال تغییرمحیط ثابت و تکراری
RRTConnect: دو درخت Start Goal PRM: نقشه جاده تصادفی
سمت راست: RRTConnect دو درخت را از Start و Goal رشد می‌دهد. سمت چپ: PRM ابتدا یک شبکه ثابت از نقاط تصادفی می‌سازد.

۱۳.۹از Path تا Trajectory اجراشدنی

Planner فقط یک Path پیدا می‌کند — دنباله‌ای از زاویه‌های مفصل بدون هیچ اطلاعاتی درباره زمان. این مسیر خام معمولاً گوشه‌های تیز دارد که برای اجرای فیزیکی مناسب نیست، پس MoveIt آن را با Path Smoothing نرم می‌کند.

📖 تفاوت Path و Trajectory

Path فقط مسیر است. Trajectory یعنی مسیر + زمان — مثلاً «ثانیه صفر: Joint1=0°، ثانیه یک: Joint1=20°، ثانیه دو: Joint1=35°». این Trajectory نهایی است که Controller (فصل ۸) واقعاً اجرا می‌کند.

در ساخت Trajectory نهایی، MoveIt چند محدودیت را هم رعایت می‌کند:

محدودیتمعنی
Velocity Limitسرعت هیچ مفصلی از حد مجاز بیشتر نشود
Acceleration Limitشتاب ناگهانی نداشته باشد
Jerkحتی تغییر ناگهانی شتاب هم در ربات‌های صنعتی حرفه‌ای محدود می‌شود

مرکز اصلی این هماهنگی، Node معروفی به‌نام move_group است:

flowchart LR A["RViz / کاربر"] --> B["move_group"] --> C["OMPL Planner"] --> D["Trajectory"] --> E["ros2_control"] --> F["Robot"] style B fill:#eef0ff,stroke:#3d4bf5
⚠️ Planner همیشه «بهترین» مسیر را پیدا نمی‌کند

RRT و RRTConnect یک مسیر خوب و امن پیدا می‌کنند، نه لزوماً بهترین مسیر ریاضی دنیا — چون یافتن مسیر مطلقاً بهینه ممکن است ساعت‌ها طول بکشد. MoveIt یک Planning Time محدود دارد (مثلاً ۵ ثانیه)؛ اگر تا آن زمان مسیری پیدا نشود، پاسخ Planning Failed برمی‌گردد.

۱۳.۱۰جمع‌بندی فصل سیزدهم

حالا می‌دانی وقتی ARCHO دستش را برای برداشتن یک جعبه بلند می‌کند، پشت صحنه چه اتفاقی می‌افتد: FK محاسبه می‌کند بازو الان کجاست، IK محاسبه می‌کند برای رسیدن به هدف مفصل‌ها چه زاویه‌ای لازم دارند، Planning Scene دنیای اطراف را در حافظه نگه می‌دارد، Collision Detection مسیر را تأیید ایمنی می‌کند، و OMPL در فضای چندبعدی Configuration Space یک مسیر امن پیدا می‌کند که در نهایت به یک Trajectory قابل اجرا تبدیل می‌شود.

✅ نقطه بازبینی یادگیری
  • می‌توانم تفاوت FK و IK را با یک مثال از دست خودم توضیح دهم.
  • می‌دانم چرا IK ممکن است چند جواب، هیچ جواب، یا بی‌نهایت جواب داشته باشد.
  • می‌توانم بگویم Planning Scene چیست و چرا ثابت نیست.
  • می‌دانم چرا MoveIt در فضای زاویه مفصل‌ها جستجو می‌کند، نه در فضای فیزیکی اتاق.
  • می‌توانم تفاوت RRTConnect و PRM را توضیح دهم و بگویم هرکدام برای چه محیطی مناسب‌تر است.
  • می‌دانم فرق Path و Trajectory چیست.
🌍 ارتباط با پروژه اصلی

پروژه ARCHO اکنون یک پیکربندی کامل MoveIt دارد که با استفاده از Planning Scene، Collision Detection و الگوریتم RRTConnect می‌تواند بازوی برداشتش را برای گرفتن جعبه از قفسه، بدون برخورد با محیط، هدایت کند.

فصل بعد چه چیزی اضافه می‌کند

در فصل چهاردهم از یک ARCHO تنها فاصله می‌گیریم و وارد دنیای چند رباتی می‌شویم: Namespace، TF Prefix و هماهنگی چند ARCHO که هم‌زمان در یک انبار کار می‌کنند.

واژه‌نامه فصل سیزدهم

MoveIt 2
چارچوب اصلی ROS 2 برای برنامه‌ریزی حرکت بازوهای رباتیک.
Forward Kinematics (FK)
محاسبه موقعیت نوک بازو از روی زاویه مفصل‌ها.
Inverse Kinematics (IK)
محاسبه زاویه لازم مفصل‌ها برای رسیدن به یک موقعیت هدف.
End Effector
آخرین قطعه بازو که کار اصلی را انجام می‌دهد؛ مثل Gripper یا Welding Torch.
Singularity
وضعیتی هندسی که حرکت بازو در بعضی جهت‌ها ناگهان سخت یا غیرممکن می‌شود.
Planning Scene
مدل دیجیتالی و به‌روز از تمام اجسام اطراف ربات که ممکن است با آن برخورد کنند.
Attached Object
جسمی که ربات آن را گرفته و از آن لحظه به‌عنوان بخشی از خود ربات محاسبه می‌شود.
Configuration Space (C-Space)
فضای چندبعدی متشکل از زاویه تمام مفصل‌های ربات که MoveIt در آن جستجو می‌کند.
OMPL
Open Motion Planning Library؛ کتابخانه‌ای که الگوریتم‌های واقعی مسیریابی MoveIt را اجرا می‌کند.
RRT / RRTConnect
الگوریتم‌های مسیریابی مبتنی بر رشد درخت تصادفی در Configuration Space.

خطاهای رایج فصل سیزدهم — جمع‌بندی