فرض کن به ARCHO مأموریت میدهی: «برو قفسه شماره ۱۲.» حالا وسط راه هرکدام از اینها ممکن است اتفاق بیفتد:
اگر منطق ARCHO فقط یک برنامه خطی ساده باشد:
در یک برنامه خطی، اولین اتفاق غیرمنتظره کل برنامه را متوقف میکند. اگر بنویسی Move → Pick →
Return و مرحله اول شکست بخورد، کل زنجیره فرو میریزد. اما در دنیای واقعی، یک ربات صنعتی باید
بتواند تصمیم بگیرد — نه فقط اجرا کند.
راهحل ROS 2 برای این مشکل، ساختاری است بهنام Behavior Tree.
Behavior Tree ساختاری درختی برای تصمیمگیری است که به ربات اجازه میدهد بر اساس شرایط لحظهای محیط، بهترین رفتار را انتخاب کند — بهجای اجرای کورکورانه یک زنجیره ثابت از دستورها.
صبح که از خانه بیرون میروی، در ذهنت این اتفاق میافتد: «آیا باران میبارد؟ اگر بله، چتر بردار؛ اگر نه، بدون چتر برو.» این دقیقاً یک Behavior Tree است — یک شرط، و بسته به نتیجهاش، یک عمل متفاوت.
چون تصمیمها شاخهدار هستند، ساختار درختی معنا پیدا میکند:
تقریباً هر Behavior Tree واقعی، از ترکیب همین سه نوع Node ساخته میشود:
| نوع Node | کار | مثال |
|---|---|---|
| Condition | فقط یک سؤال میپرسد؛ خروجی فقط Success یا Failure است | Battery OK؟ Goal Reached؟ |
| Action | کاری واقعی انجام میدهد | Compute Path، Follow Path، Rotate، Clear Costmap |
| Control | تصمیم میگیرد کدام شاخه اجرا شود — مهمترین بخش BT | Sequence، Fallback، Parallel |
همه مراحل باید یکییکی موفق شوند؛ اگر یکی شکست بخورد، بقیه اصلاً اجرا نمیشوند.
اگر گزینه اول شکست خورد، گزینه بعدی امتحان میشود.
چند کار را همزمان اجرا میکند — ARCHO فقط حرکت نمیکند، بلکه همزمان باتری، LiDAR و مقصد را هم زیر نظر دارد.
هر Node در یک لحظه یکی از این سه وضعیت را برمیگرداند:
| وضعیت | معنی |
|---|---|
Success | کار با موفقیت انجام شد |
Failure | کار انجام نشد |
Running | هنوز در حال انجام است — مثلاً ARCHO هنوز در حال حرکت است |
Behavior Tree فقط یکبار اجرا نمیشود؛ دائماً و مکرراً (مثلاً ۲۰ بار در ثانیه) از ریشه بررسی میشود. هر بار بررسی را Tick مینامند. در هر Tick دوباره پرسیده میشود: مقصد عوض شده؟ مانع جدید آمده؟ باتری کم شده؟ مسیر هنوز معتبر است؟
اگر بخواهی همه این شرایط را با if battery، if obstacle، if
planner، if recovery، if localization، if timeout و
if sensor بنویسی، خیلی زود کد به یک آشفتگی غیرقابل نگهداری تبدیل میشود. Behavior Tree
همین پیچیدگی را در قالب یک ساختار بصری و قابل توسعه سازماندهی میکند.
نسخه سادهشده:
اما نسخه واقعی که Nav2 اجرا میکند شکل کاملتری دارد:
اگر Global Planner نتواند مسیر پیدا کند، BT بهجای فروپاشی، یک زنجیره بازیابی را امتحان میکند:
اگر Planner قبلاً مسیری از یک راهرو پیدا کرده بود اما حالا آن راهرو مسدود شده، Behavior Tree خودش تصمیم میگیرد Planner دوباره اجرا شود و مسیر تازهای محاسبه کند — بدون اینکه خط جدیدی از کد نوشته شود.
اگر باتری ARCHO به ۸٪ برسد، BT میتواند بدون اینکه برنامهنویس صدها شرط if بنویسد، تصمیم
بگیرد: مأموریت را لغو کن، برو ایستگاه شارژ.
مأموریت «برو قفسه ۱۲» در قالب BT چیزی شبیه این است: Battery OK؟ → Localization OK؟ → Compute Path → Follow Path → Goal Reached؟ → Recovery. اگر وسط راه یک کارگر عبور کند، Planner دوباره مسیر را محاسبه میکند و ARCHO ادامه میدهد؛ اگر این هم جواب نداد، Recovery فعال میشود — کمی عقب میرود، دوباره تلاش میکند، یا در نهایت مأموریت را لغو میکند.
فرض کن ARCHO را روشن میکنی. آیا منطقی است که بلافاصله LiDAR شروع به کار کند، Planner اجرا شود، Controller فرمان بدهد و موتورها حرکت کنند — بدون اطمینان از سالمبودن همهچیز؟ قطعاً نه.
خلبان فقط دکمه روشن را نمیزند و پرواز نمیکند. اول موتور، سوخت، سیستم هیدرولیک و ابزارها بررسی میشوند و بعد اجازه پرواز داده میشود. ROS 2 دقیقاً همین منطق را برای Nodeهای حیاتی پیاده کرده است.
در ROS 1، Nodeها معمولاً فقط دو حالت داشتند: Start و Running. اگر مشکلی پیش
میآمد، مدیریت آن سخت بود چون هیچ حالت میانی کنترلشدهای وجود نداشت. ROS 2 این را با
Lifecycle Node حل کرده است.
Lifecycle Node، Nodeای است که وضعیتهای مشخصی دارد و فقط زمانی کاملاً فعال میشود که همه شرایط لازم برقرار باشند — نه بهمحض روشنشدن.
توجه: علاوه بر این چهار حالت اصلی (Unconfigured, Inactive, Active, Finalized)، هر گذار بین آنها (مثل Configure یا Activate) عملاً از یک حالت گذار موقت (Transition State) عبور میکند؛ این حالتهای گذار در نمودار سادهشده بالا نشان داده نشدهاند.
| حالت | معنی | مثال LiDAR Driver |
|---|---|---|
| Unconfigured | Node وجود دارد، اما هنوز آماده کار نیست | پورت سریال هنوز باز نشده |
| Inactive | Node آماده است اما هنوز کاری انجام نمیدهد | LiDAR آماده است اما هنوز داده منتشر نمیکند |
| Active | Node واقعاً در حال کار است — Topic منتشر، Service پاسخ میدهد | LaserScan روی /scan منتشر میشود |
| Finalized | Node بهطور کامل و برگشتناپذیر بسته شده — از هر سه حالت دیگر قابل دسترسی است | خاموشی کامل سیستم |
فرض کن Planner آماده است اما Localization هنوز آماده نشده. اگر Planner همین الان فعال شود، اطلاعات موقعیت اشتباه دریافت میکند و مسیرهای غلط تولید میکند. حالت Inactive به Planner اجازه میدهد «آماده اما ساکت» بماند تا وقتی که واقعاً وقتش برسد.
اگر Controller قبل از Localization فعال شود، ARCHO ممکن است بر اساس موقعیت اشتباه حرکت کند — که در یک انبار پر از قفسه و کارگر، خطرناک است. Lifecycle دقیقاً همین ترتیب را کنترل میکند: LiDAR → TF → Localization → Costmap → Planner → Controller.
در Navigation2 یک Node مرکزی بهنام Lifecycle Manager وجود دارد که مثل یک مدیر پروژه عمل میکند: Configure → Activate → Monitor → Shutdown را برای تمام Nodeهای حیاتی هماهنگ میکند.
شیفت شب در یک کارخانه شروع میشود. ARCHO روشن میشود؛ Lifecycle Manager بررسی میکند LiDAR، IMU و Encoder سالماند. AMCL فعال میشود و موقعیت را پیدا میکند. Planner و Controller فعال میشوند و ARCHO شروع به کار میکند. در میانه شیفت، LiDAR بهطور موقت از دسترس خارج میشود — Lifecycle Manager فوراً Planner و Controller را به Inactive میبرد تا ARCHO حرکت خطرناک نکند. وقتی LiDAR دوباره سالم شد، Nodeها به همان ترتیب منطقی دوباره فعال میشوند. این رفتار، سیستم را قابل پیشبینی و ایمن نگه میدارد.
Behavior Tree تصمیم میگیرد چه کاری الان انجام شود. Lifecycle تصمیم میگیرد کدام Node اصلاً اجازه اجرا دارد. یکی مغز تصمیمگیری لحظهای است، دیگری چارچوب ایمنی راهاندازی و توقف.
حالا معماری کامل Navigation2 برایت روشن شد: Localization، Map، Costmap، Global Planner و Local Controller (فصل ۱۱)، بههمراه Behavior Tree که همه اینها را هماهنگ میکند و Lifecycle Nodes که تضمین میکند هر بخش فقط وقتی فعال شود که واقعاً آماده است. این ششبخش با هم باعث میشوند ARCHO بتواند در یک محیط واقعی — با موانع متحرک، تغییر مسیر، خطای سنسور و شرایط غیرمنتظره — کنار بیاید.
پروژه ARCHO اکنون یک معماری کامل Nav2 دارد: BT Navigator که تصمیمگیری لحظهای را هماهنگ میکند، و Lifecycle Manager که ترتیب امن راهاندازی و بازیابی همه Nodeهای حیاتی را کنترل میکند.
در فصل سیزدهم به سراغ MoveIt 2 میرویم — اگر ARCHO یک بازوی رباتیک هم داشته باشد، اینجا یاد میگیریم چطور آن بازو مسیر حرکت خودش را برنامهریزی میکند.