דלג לתוכן הראשי

כיוון עם בקרה חזותית

  1. אתה יכול לכוון את הרובוט שלך במדויק ובמהירות באמצעות limelight ומערכת ההנעה בלבד.
  2. ניתן להשיג את כל זה בפחות משעה אחת.

באמצעות מעקב חזותי בקצב פריימים גבוה, כעת אפשר להשתמש במערכת הראייה ישירות כ"חיישן" בלולאת בקרת PID כדי להנחות את הרובוט או המגדל שלך. כדי לבדוק את הרעיון הזה, הוספנו limelight לרובוט ה-FRC משנת 2017 שלנו וגרמנו לו לכוון למטרות חזותיות באמצעות מערכת ההנעה ונתוני טבלת הרשת המדווחים על ידי ה-limelight בלבד.

בדוגמה זו, הנבדק שלנו היה רובוט FRC משנת 2017 המשתמש במערכת הנעה בעלת 6 גלגלים עם גלגלי colson. הנה תמונה שלנו מוסיפים limelight לרובוט כדי לבצע את הבדיקה הזו.

CS_aim_limelight_mounted

לאחר מכן הוספנו קוד לרובוט שירוץ בכל פעם שהנהג מחזיק לחצן בג'ויסטיק. רובוט זה השתמש בנהיגה בסגנון "טנק" כך שפונקציית 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 גבוה מדי, הרובוט שלך עלול להיות לא יציב ולהתנדנד הלוך ושוב כשהוא חורג מהמטרה:

CS_aim_bad

לאחר כיוון מסוים של Kp ו-min_command, הרובוט שלך אמור לכוון ישירות למטרה במדויק ובמהירות.

CS_aim_good