انتقل إلى المحتوى الرئيسي

التصويب باستخدام التوجيه البصري

  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