Utiliser les modules Yoctopuce avec le jeu iRacing

Utiliser les modules Yoctopuce avec le jeu iRacing

IRacing est un jeu une simulation de course avec une physique réaliste. Pour tester cette simulation, nous avons dépoussiéré un vieux volant Logitec G25 qui fonctionne encore très bien, mais qui ne possède pas de LEDs ou d'affichage qui peut être contrôlé par le jeu. Du coup, on s'est dit que c’était l'occasion d'ajouter ces fonctionnalités en utilisant des modules Yoctopuce. Et comme nous allons le voir, ce n'est pas très compliqué.



La première étape est de regarder quelles informations on peut obtenir du jeu. En parcourant les forums d'iRacing, on découvre qu'il existe un SDK qui permet de récupérer facilement toutes les informations de télémétrie de la voiture (vitesse, compte tour, rapport engagée, etc.). Quelqu'un a même écrit une libraire en Python qui permet d'interfacer facilement avec ce SDK: Python iRacing SDK

On installe cette librairie ainsi que notre librairie Python à l'aide de la commande pip install.

pip install pyirsdk yoctopuce



Après avoir installé les librairies, on vérifie que l'on arrive à obtenir le rapport engagé.

#!python3
import irsdk
ir = irsdk.IRSDK()
ir.startup()
print(ir['Gear'])



Le code fonctionne, mais uniquement quand le jeu est lancé et ne fait qu'afficher le rapport sur le terminal du PC.

En s'inspirant des exemples disponibles, on crée un code qui vérifie si le jeu est lancé et qui appelle la méthode refresh 60 fois par seconde si une partie est en cours. Dans ce code on ajoute aussi les appels à YAPI.RegisterHub, YAPI.RegisterDeviceArrivalCallback, YAPI.RegisterDeviceRemovalCallback et YAPI.UpdateDeviceList qui permettent de gérer correctement le hotplug des modules Yoctopuce.

Si vous ne connaissez pas bien ces fonctions, nous avons un article qui explique leur fonctionnement.

def deviceArrival(self, m: YModule):
  serial = m.get_serialNumber()
  if m.get_productName().startswith("Yocto-MaxiDisplay"):
    self.display = YDisplay.FindDisplay(serial + ".display")
    self.configure_display()

def deviceRemoval(self, m):
  serial = m.get_serialNumber()
  if self.display is not None and serial == self.display.get_serialNumber():
    self.display = None

def loop(self):
  self.ir = irsdk.IRSDK()
  errmsg = YRefParam()
    err = YAPI.RegisterHub(hub, errmsg)
    if err != YAPI.SUCCESS:
      sys.exit("Unable to register " + hub + " : " + errmsg.value)
  YAPI.RegisterDeviceArrivalCallback(self.deviceArrival)
  YAPI.RegisterDeviceRemovalCallback(self.deviceRemoval)
  # infinite loop
  while True:
    # check if we are connected to iracing
    if self.ir_connected
           and not (self.ir.is_initialized and self.ir.is_connected):
        self.ir_connected = False
        self.last_car_setup_tick = -1
        self.ir.shutdown()
        print('irsdk disconnected')
    elif not self.ir_connected and self.ir.startup()
            and self.ir.is_initialized and self.ir.is_connected:
        self.ir_connected = True
        print('irsdk connected')
    if self.ir_connected:
        self.refresh()
    # Check for Yoctopuce devices arrival or removal
    YAPI.UpdateDeviceList()
    # sleep ~1/60s
    YAPI.Sleep(16)

def configure_display(self):
 ...

def refresh(self):
 ...



La méthode configure_display est appelée lorsqu'un Yocto-MaxiDisplay est connecté sur le port USB. Cette fonction nettoye l'écran et stocke quelques valeurs, comme les dimensions de l'écran, dans des variables.

def configure_display(self):
    # display clean up
    self.display.resetAll()
    # retrieve the display size
    self.display_w = self.display.get_displayWidth()
    self.display_h = self.display.get_displayHeight()
    # retrieve the first layer
    self.layer0 = self.display.get_displayLayer(0)



Comme nous l'avons vu plus haut, la méthode refresh est appelée uniquement quand iRacing est lancé. Cette méthode lit le rapport engagé grâce à l'attribut "Gear" de l'objet IRSDK. la valeur -1 correspond à la marche arrière, 0 correspond au point neutre et les valeurs positives indiquent le rapport engagé. Si le rapport a changé, on met à jour l'écran du Yocto-MaxiDisplay à l'aide de la méthode drawText.

def refresh(self):
    if self.display is not None:
        gear_char = 'X'
        gear = self.ir['Gear']
        if gear < 0:
            gear_char = 'R'
        elif gear == 0:
            gear_char = 'N'
        else:
            gear_char = "%d" % gear
        if gear_char != self.lastGear:
            self.layer0.clear()
            self.layer0.selectFont("Large.yfm")
            self.layer0.drawText(self.display_w / 2, self.display_h / 2, YDisplayLayer.ALIGN.CENTER, gear_char)
            self.lastGear = gear_char



Il ne reste qu'à fixer le Yocto-MaxiDisplay sur la base du volant et voilà!

Le Yocto-MaxiDisplay affiche le rapport de la voiture
Le Yocto-MaxiDisplay affiche le rapport de la voiture



Comme nous avons pris soin de gérer correctement le hot-plug des modules Yoctopuce et la connexion avec iRacing, on peut lancer ce programme pendant une partie ou au contraire avant de démarer le jeu. Pareil pour les modules Yoctopuce, il est possible de les brancher et débrancher à n'împorte quel moment.

Comme d'habitue le code source complet est disponible sur GitHub:
https://github.com/yoctopuce-examples/yocto_iracing_info.

Afin de garder l'article assez concis, nous nous sommes limité à expliquer comment afficher le rapport engagé, mais le SDK publie un grand nombre d'informations et il est très facile de modifier le code pour afficher d'autres informations. Du reste, la version disponible sur GitHub inclut quelques petites fonctionnalités supplémentaires...

Par exemple si vous avez branché un Yocto-Color-V2, les LEDs seront utilisées comme shift-light.

Le Yocto-Color-V2 est utilisé comme shift-light
Le Yocto-Color-V2 est utilisé comme shift-light


Commenter aucun commentaire Retour au blog












Yoctopuce, get your stuff connected.