Aller au contenu principal

Viser avec l'asservissement visuel

  1. Vous pouvez viser avec précision et rapidité en utilisant uniquement une limelight et votre châssis roulant.
  2. Tout cela peut être accompli en moins d'une heure.

En utilisant le suivi visuel à haute fréquence d'images, il est maintenant possible d'utiliser le pipeline de vision directement comme "capteur" dans une boucle de contrôle PID pour guider votre robot ou tourelle. Afin de tester cette idée, nous avons ajouté une limelight à notre robot FRC 2017 et l'avons fait viser des cibles visuelles en utilisant uniquement le châssis roulant et les données de la table réseau rapportées par la limelight.

Dans cet exemple, notre candidat de test était un robot FRC 2017 qui utilise un châssis roulant à 6 roues avec des roues colson. Voici une photo de nous ajoutant une limelight sur le robot pour effectuer ce test.

CS_aim_limelight_mounted

Ensuite, nous avons ajouté du code au robot qui s'exécuterait chaque fois que le pilote maintient un bouton sur le joystick. Ce robot utilisait une conduite de style "tank", donc la fonction OperatorControl générait une valeur 'left_command' et une valeur 'right_command' pour contrôler les côtés gauche et droit du châssis roulant. Après le code de contrôle normal, nous avons ajouté un bloc de code comme celui-ci :

float Kp = -0.1f;  // Constante de contrôle proportionnel

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;
}

D'emblée, cela fonctionnait plutôt bien. Le robot tourne dans la direction de la cible automatiquement chaque fois que vous maintenez le bouton. Si vous déplacez la cible, le robot tourne pour suivre la cible. Cependant, en utilisant le flux vidéo en direct sur le tableau de bord, nous pouvions voir qu'il y avait un gros problème : Le robot n'arrivait pas toujours à s'aligner parfaitement avec la cible. Dans certains jeux avec de petites cibles (comme 2016 et 2017), cela ne serait pas suffisant.

Ce que nous avons implémenté jusqu'à présent est une simple boucle de contrôle proportionnel. Nous avons calculé l'erreur de cap et l'avons multipliée par une constante, créant ainsi une commande moteur proportionnelle à l'erreur. Lorsque l'erreur tend vers zéro, notre commande tend vers zéro. Le problème est qu'il y a beaucoup de friction impliquée lorsque le robot essaie de tourner. De très petites commandes ne feront pas tourner le robot du tout. À de petits angles, la commande peut devenir trop faible pour réellement déplacer le robot. Vous pourriez constater que votre robot atteint bien sa cible lorsque vous commencez avec une grande erreur de visée, mais qu'il ne peut tout simplement pas viser si vous commencez très proche.

Il existe plusieurs façons de résoudre ce problème, mais voici une solution vraiment simple. Nous avons utilisé un concept de "commande minimale". Si l'erreur est supérieure à un certain seuil, ajoutez simplement une constante à votre commande moteur qui représente approximativement la puissance minimale nécessaire pour que le robot bouge réellement (vous voulez en fait utiliser un peu moins que cela). Le nouveau code ressemble à ceci :

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;
}

Attention, si vous réglez Kp ou min_command trop haut, votre robot peut devenir instable et osciller d'avant en arrière en dépassant la cible :

CS_aim_bad

Après quelques ajustements de Kp et min_command, vous devriez obtenir que votre robot vise directement la cible avec précision et rapidité.

CS_aim_good