כיוון באמצעות שירות חזותי
- ניתן לכוון את הרובוט שלך במדויק ובמהירות באמצעות limelight ומערכת ההנעה בלבד.
- ניתן להשיג את כל זה בפחות משעה אחת.
באמצעות מעקב חזותי בקצב פריימים גבוה, כעת ניתן להשתמש בצינור הראייה ישירות כ"חיישן" בלולאת בקרת PID כדי להנחות את הרובוט או המגדל שלך. כדי לבדוק רעיון זה, הוספנו limelight לרובוט ה-FRC משנת 2017 שלנו וגרמנו לו לכוון למטרות חזותיות באמצעות מערכת ההנעה ונתוני טבלת הרשתות המדווחים על ידי ה-limelight בלבד.
בדוגמה זו, מועמד הבדיקה שלנו היה רובוט FRC משנת 2017 המשתמש במערכת הנעה בעלת 6 גלגלים עם גלגלי colson. הנה תמונה של הוספת limelight לרובוט כדי לבצע בדיקה זו.
לאחר מכן הוספנו קוד לרובוט שיפעל בכל פעם שהנהג מחזיק לחצן בג'ויסטיק. רובוט זה השתמש בנהיגה בסגנון "טנק" כך שפונקציית OperatorControl יצרה ערך 'left_command' וערך 'right_command' כדי לשלוט בצדדים השמאלי והימני של מערכת ההנעה. לאחר קוד הבקרה הרגיל, הוספנו בלוק קוד כזה:
float Kp = -0.1f; // קבוע בקרה פרופורציונלית
std::shared_ptr<NetworkTable> table = NetworkTable::GetTable("limelight");
float tx = table->GetNumber("tx");
if (joystick->GetRawButton(9))
{
float heading_error = tx;
steering_adjust = Kp * tx;
left_command+=steering_adjust;
right_command-=steering_adjust;
}
מיד מההתחלה, זה עבד ברובו. הרובוט מסתובב לכיוון המטרה באופן אוטומטי בכל פעם שאתה מחזיק את הלחצן. אם אתה מזיז את המטרה, הרובוט מסתובב כדי לעקוב אחר המטרה. עם זאת, באמצעות הזנת הווידאו החי בלוח המחוונים, יכולנו לראות שהייתה בעיה גדולה אחת: הרובוט לא תמיד הגיע עד הסוף כדי להתיישר בצורה מושלמת עם המטרה. בכמה משחקים עם מטרות קטנות (כמו 2016 ו-2017) זה לא היה מספיק טוב.
מה שיישמנו עד כה הוא לולאת בקרה פרופורציונלית פשוטה. חישבנו את השגיאה בכיוון והכפלנו אותה בקבוע, ובכך יצרנו פקודת מנוע שהיא פרופורציונלית לשגיאה. ככל שהשגיאה מתקרבת לאפס, הפקודה שלנו תתקרב לאפס. הבעיה היא שיש הרבה חיכוך כאשר הרובוט מנסה להסתובב. פקודות קטנות מאוד לא יסובבו את הרובוט בכלל. בזוויות קטנות, הפקודה יכולה להיות קטנה מדי כדי להזיז את הרובוט בפועל. ייתכן שתגלה שהרובוט שלך מגיע למטרה היטב כאשר אתה מתחיל עם שגיאת כיוון גדולה, אבל הוא פשוט לא יכול לכוון בכלל אם אתה מתחיל ממש קרוב.
יש כמה דרכים לפתור בעיה זו, אבל הנה פתרון פשוט מאוד. השתמשנו במושג "פקודה מינימלית". אם השגיאה גדולה מסף מסוים, פשוט הוסף קבוע לפקודת המנוע שלך שמייצג בערך את כמות הכוח המינימלית הנדרשת כדי שהרובוט יזוז בפועל (למעשה אתה רוצה להשתמש בקצת פחות מזה). הקוד החדש נראה כך:
float Kp = -0.1f;
float min_command = 0.05f;
std::shared_ptr<NetworkTable> table = NetworkTable::GetTable("limelight");
float tx = table->GetNumber("tx");
if (joystick->GetRawButton(9))
{
float heading_error = -tx;
float steering_adjust = 0.0f;
if (Math.abs(heading_error) > 1.0)
{
if (heading_error < 0)
{
steering_adjust = Kp*heading_error + min_command;
}
else
{
steering_adjust = Kp*heading_error - min_command;
}
}
left_command += steering_adjust;
right_command -= steering_adjust;
}
היזהר, אם תגדיר את Kp או min_command גבוה מדי, הרובוט שלך עלול להיו ת לא יציב ולהתנדנד הלוך ושוב כשהוא חורג מהמטרה:
לאחר כמה כיוונונים של Kp ו-min_command, הרובוט שלך אמור לכוון ישירות למטרה במדויק ובמהירות.