Les parts dans le Framework Donkey Car | SIGMA IA RACING

Nos 3 étudiants de B3 développement et M1 développement poursuivent leur projet <IA/> RACING. Pour rappel, ce projet pédagogique consister à créer une IA capable de réaliser le meilleur chrono sur un circuit grâce à une voiture autonome.

Rappels sur le framework et l'utilisation des parts

Nous avions évoqué plus tôt, le framework Donkey Car dans ce projet. Nos étudiants ont ainsi pu assister à une réunion d’informations afin de mieux appréhender le concept de “parts” qui permettent d’accélérer la vitesse de la boucle principale.

Pour rappel, le framework Donkey Car est composé de deux dossiers principaux : 

  •  Le dossier Donkey Car, tiré du Git et où est regroupé l’ensemble du framework. Ce dossier comprend le fichier principal vehicle.py ainsi que les différentes “parts” ajoutés grâce au manage.py.
  • Le dossier cars contenant les instances de voiture ainsi que les fichiers de configuration et le fichier manage.py. Ce dernier, sert de lanceur indépendant pour chaque voiture. Il instancie ainsi le fichier vehicle.py. Ce dossier dispose également de deux fichiers de configuration : config.py qui est le fichier de base, et myconfig.py qui est le fichier de configuration spécifique à la voiture qui est développée.
Dossiers Donkey car
Quant aux parts, celles-ci sont composées de 2 parties distinctes : l’initialisation et l’exécution de la boucle principaleCette boucle sert à exécuter l’ensembles des parts de manière séquentielle, en fonction de l’ordre d’instanciation dans le manage.py. Cette boucle peut être exécutée  :
  •  De manière synchrone, c’est-à-dire que chaque part s’exécute l’une après l’autre et en résulte un temps d’exécution et donc une fréquence. Celui-ci ne doit pas descendre sous les 10Hz.

Donkey Car part synchrone

  • Via l’utilisation de threaded parts, c’est-à-dire, une part indépendante qui s’exécute sans impacter la boucle principale et donc sa vitesse d’exécution.

Donkey car threaded part

Développer la part d'information et en mesurer son temps d'exécution

Cette part sert à remonter la fréquence d’exécution de l’ensemble des parts. Elle peut également servir à termes, à remonter tout type d’informations (accélération, direction en cours…).

Développer la part information de manière synchrone

Cette part test_information.py, comme toutes les parts, est composée d’une classe, ici : 

class TestInformation(object) et de deux fonctions : def __init__(self) servant à initialiser nos variables, ici, self.care_frequency = 0 et self.last_calc_time = time.time();  et def run(self) pour exécuter ce que l’on souhaite.

Afin que cette part soit prise en compte, il faut l’ajouter au fichier manage.py ou complete.py (si vous souhaitez impacter toutes vos voitures) et l’importer de cette manière au fichier :

from donkeycar.parts.test_information import TestInformation
V.add(TestInformation())

Pour mesurer son temps d’exécution, il faut importer la librairie time et implémenter dans la fonction run() :

self.car_frequency = 1/(time.time()-self.last_calc_time)
self.last_calc-time = time.time()

Puis, pour l’afficher à l’écran : print(” Frequency : ” + str(self.car_frequency) + “Hz”)

Fréquence part synchrone

Cependant, l’utilisation de cette part rallonge en moyenne de 2.28ms l’exécution de l’ensemble de la boucle. Pour optimiser cela, il faut utiliser une threaded part.

Transformer notre part en threaded part

Afin de transformer notre part synchrone en threaded part, plusieurs modifications sont à réaliser :

  •  Dans le fichier manage.py, il faut ajouter “threaded = True” à
    from donkeycar.parts.test_information import TestInformation
    V.add(TestInformation(), threaded=True)
  • Dans le fichier test_information.py, il faut rajouter la fonction update et modifier son code de la façon suivante.

def __init__(self) :
self.on = True // variable qui sert à indiquer à la fonction update le démarrage de la part
self.care_frequency = 0
self.last_calc_time = time.time()

def shutdown(self) :  // Cette fonction permet d’arrêter la part lorsque la commande associée est effectuée
self.on = False

def update(self) : // Cette fonction s’exécute dès lors où on initialise la part
while self.on : // Tant que la boucle est en cours, les actions ci-dessous s’effectuent
print(” Frequency : ” + str(self.car_frequency) + “Hz”)
time.sleep(5) // Afin que cette fonction ne s’exécute que toutes les 5 secondes pour ne pas polluer l’écran
 
def run_threaded(self):
self.car_frequency = 1/(time.time()-self.last_calc_time)
self.last_calc-time = time.time()

/evenement/parts-framework-donkey-car/2022-02-23Outil

Par Léna Queguiner
Chargée de communication