Enregistrer l'angle d'une moto dans un virage

Enregistrer l'angle d'une moto dans un virage

Ce qui est le plus impressionnant dans une course de moto, c'est la façon dont les pilotes penchent leur moto dans les virages. Les télévisons diffusent souvent des vidéos de caméras embarquées et incrustent l'angle maximum atteint. Lors d'un grand prix, ces informations sont récupérées par télémétrie, et diffusées en directe, mais est-il possible de réaliser une vidéo du même genre (mais en différé) en utilisant un Yocto-3D et une GoPro?


Pour réaliser une vidéo de ce type, il faut être capable d'enregistrer la vidéo et la position de la moto. Pour enregistrer la vidéo, nous utilisons une caméra GoPro qui est fixée à l’arrière de la moto. Pour enregistrer la position de la moto, on utilise un Yocto-3D qui est alimenté par une batterie USB. Le Yocto-3D peut être fixé n'importe où sur la moto pour autant qu'il soit dans l'axe de la moto et fixé horizontalement (on pourrait fixer le Yocto-3D dans n'importe quel sens mais cela complique énormément le calcul de l'angle car il faut tenir compte de sa position initiale). Pour garder tout le système accessible, le Yocto-3D est fixé à côté de la GoPro.

La GoPro, le Yocto-3D et la batterie fixés sur le becquet de selle de la moto
La GoPro, le Yocto-3D et la batterie fixés sur le becquet de selle de la moto



Pour incruster l'angle de la moto sur la vidéo, nous avons écrit un petit programme en C#. Nous avons choisi C# car nous utilisons la librairie AForge, mais il est tout à fait possible d'écrire un programme équivalent avec un autre langage ou une autre librairie vidéo. Ce programme à deux fonctions: Premièrement, configurer le Yocto-3D pour qu'il démarre un enregistrement dès qu'il est sous tension. Deuxièmement, charger les valeurs enregistrées sur la mémoire flash du Yocto-3D pour les incruster sur la vidéo de la GoPro.

Le graphique est incrusté sur la vidéo à l'aide de la librairie C# AForge
Le graphique est incrusté sur la vidéo à l'aide de la librairie C# AForge




Préparer le Yocto-3D


Par défaut, le Yocto-3D n'enregistre pas de mesure dans sa mémoire flash. Pour pouvoir utiliser le Yocto-3D comme un simple enregistreur et que les données soit utilisables par notre programme il faut:

  1. Effacer toutes les valeurs précédemment enregistrées
  2. Définir la fréquence d'enregistrement pour les 4 fonctions quaternions à 30 mesures par seconde
  3. Activer la fonction autoStart du datalogger pour que le Yocto-3D démarre l'enregistrement dès qu'il est alimenté
  4. Sauvegarder cette configuration dans la mémoire flash (pour ne pas perdre cette configuration lors du prochain débranchement)


private void ConfigureYocto3d(string serial)
{
    YDataLogger logger = YDataLogger.FindDataLogger(serial + ".dataLogger");
    logger.set_recording(YDataLogger.RECORDING_OFF);
    logger.forgetAllDataStreams();
    YQt q1 = YQt.FindQt(serial + ".qt1");
    q1.set_logFrequency("30/s");
    YQt q2 = YQt.FindQt(serial + ".qt2");
    q2.set_logFrequency("30/s");
    YQt q3 = YQt.FindQt(serial + ".qt3");
    q3.set_logFrequency("30/s");
    YQt q4 = YQt.FindQt(serial + ".qt4");
    q4.set_logFrequency("30/s");
    logger.set_autoStart(YDataLogger.AUTOSTART_ON);
    logger.get_module().saveToFlash();
}



Il est très important d’exécuter cette fonction avant de partir en balade sinon vous risquez de vous retrouver avec des données d'un enregistrement précédent ou que le Yocto-3D n'enregistre pas les bonnes informations. Il est aussi important de brancher le Yocto-3D en même temps que l'on démarre l'enregistrement de la vidéo pour que les deux soient synchronisés.

Les quaternions


Pour calculer l'angle de la moto, il est tentant d’utiliser la fonction tilt1. Mais cette fonction utilise l’accélération pour calculer l'inclinaison du module (cf présentation du module) et cette mesure est faussée durant les accélérations et freinages de la moto. De plus, cette mesure est fortement moyennée pour obtenir une grande précision et n'est rafraîchie que 10 fois par seconde. La meilleure solution est d'utiliser le gyroscope (qui n'est pas perturbé par les accélérations subies) pour calculer l'angle de la moto.

Les trois angles qui décrivent la position du module dans l'espace (l'angle de roulis, l'angle d'assiette et l'angle de tangage) sont calculés en utilisant les quatre composantes du quaternion hyper-complexe qui décrit la position du module. Normalement, vous n'avez pas à vous soucier de ce qu'est un quaternion car l'API effectue tous les calculs pour vous. Il suffit d’enregistrer une fonction de callback (à l'aide de la méthode registerAnglesCallback) pour recevoir les angles de roulis, d'assiette et de tangage dès que l'on bouge le Yocto-3D.

Malheureusement, le datalogger ne peut pas enregistrer directement les trois angles qui décrivent l'orientation du module. Il est cependant capable de stoker les quatre quaternions qui permettent de recalculer ces trois angles. Donc pour déterminer l'angle de la moto dans un virage il faut que le datalogger enregistre les quatre fonctions YQt du Yocto-3D et recalcule l'angle à l'aide du code suivant:

List<double> ComputeAngles(double w, double x, double y, double z, double defaultRoll)
{
  double sqw = 0;
  double sqx = 0;
  double sqy = 0;
  double sqz = 0;
  double norm = 0;
  double delta = 0;
  double head = 0;
  double pitch = 0;
  double roll = 0;
  List<double> res = new List<double>();
  sqw = w * w;
  sqx = x * x;
  sqy = y * y;
  sqz = z * z;
  norm = sqx + sqy + sqz + sqw;
  delta = y * w - x * z;
  if (delta > 0.499 * norm)
  {
    roll = defaultRoll;
    pitch = 90.0;
    head = Math.Round(2.0 * 1800.0 / Math.PI * Math.Atan2(x, w)) / 10.0;
  }
  else
  {
    if (delta < -0.499 * norm)
    {
      roll = defaultRoll;
      pitch = -90.0;
      head = Math.Round(-2.0 * 1800.0 / Math.PI * Math.Atan2(x, w)) / 10.0;
    }
    else
    {
      roll = Math.Round(1800.0 / Math.PI *
           Math.Atan2(2.0 * (w * x + y * z), sqw - sqx - sqy + sqz)) / 10.0;
      pitch = Math.Round(1800.0 / Math.PI *
           Math.Asin(2.0 * delta / norm)) / 10.0;
      head = Math.Round(1800.0 / Math.PI *
           Math.Atan2(2.0 * (x * y + z * w), sqw + sqx - sqy - sqz)) / 10.0;
    }
  }
  res.Add(roll);
  res.Add(pitch);
  res.Add(head);
  Console.WriteLine("w:" + w + " x:" + x + " y:" + y + " z:" + z + "-> r:" + roll);
  return res;
}



Les calculs sur les quaternions sont complexes et dépassent le cadre de cet article. La seule chose à retenir est que cette fonction prend en paramètre la valeur des quatre quaternions (W, X, Y, Z) et retourne une liste qui contient dans l'ordre: les angles de roulis, d'assiette et de tangage. Cependant, vous pouvez consulter cette page si vous voulez comprendre les détails de ce calcul.

Charger les informations du datalogger


Calculer l'angle de roulis de la moto se fait en deux étapes. Premièrement, il faut charger les valeurs des quatre quaternions que le Yocto-3D a enregistré dans sa mémoire flash.

private List<YMeasure> LoadQT(string hwid)
{
  YQt qt = YQt.FindQt(hwid);
  YDataSet dataset = qt.get_recordedData(0, 0);
  int progress=0;
  do {
    progress = dataset.loadMore();
  } while(progress <100);
  return dataset.get_measures();
}



Deuxièmement, il faut calculer l'angle de la moto depuis les quatre quaternions. Étant donné que nous avons définit une fréquence d'enregistrement de 30 mesures par seconde pour les quatre quaternions et que le datalogger synchronise l'enregistrement toutes les valeurs, les quatre tableaux qt_w, qt_x, qt_y et qt_z ont le même nombre de mensures. On applique la fonction de calcule décrite précédemment à toutes ces mesures pour obtenir un tableau avec l'angle de la moto à une fréquence de 30 mesures par seconde.

private List<int> GetAnglesList(string serial)
{
    List<YMeasure> qt_w = LoadQT(serial + ".qt1");
    List<YMeasure> qt_x = LoadQT(serial + ".qt2");
    List<YMeasure> qt_y = LoadQT(serial + ".qt3");
    List<YMeasure> qt_z = LoadQT(serial + ".qt4");
    int count = qt_w.Count;
    List<int> angles = new List<int>(count);
    for (int i = 0; i < count; i++)
    {
         List<double> pos = ComputeAngles(qt_w[i].get_averageValue(),
            qt_x[i].get_averageValue(),
            qt_y[i].get_averageValue(),
            qt_z[i].get_averageValue(),
            0);
         angles.Add((int)Math.Round(pos[0]));
    }
    return angles;
}



Maintenant que nous avons la vidéo de la GoPro et un tableau avec les angles de la moto, il reste à dessiner le graphique sur chaque frame de la vidéo. Nous allons passer sous silence cette partie car cela reviendrait à écrire un tutoriel sur AForge. Cependant, si vous désirez voir les détails de la partie "graphique", vous pouvez télécharger le projet complet sur GitHub.

Conclusion


Il est effectivement possible de réaliser une vidéo qui affiche l'angle de la moto à l'aide d'un Yocto-3D.

  
Et voilà le résultat



Comme vous pouvez le voir, le résultat est plutôt convainquant. Hormis la fonction qui calcule l'angle depuis les quatre quaternions, le code est assez simple. Mais devoir démarrer l'enregistrement de la vidéo et brancher le Yocto-3D en même temps nécessite une certaine dextérité et influe grandement sur la qualité du résultat. Toutefois, la plus grosse difficulté reste quand même d'atteindre un angle impressionnant en moto :-)

Commenter aucun commentaire Retour au blog












Yoctopuce, get your stuff connected.