Skip to content
This repository has been archived by the owner on Oct 25, 2023. It is now read-only.

ai_scheduler

Pierre Laclau edited this page Feb 12, 2018 · 13 revisions

Description

Le scheduler est le coeur de l'Intelligence Artificielle du robot. Il est chargé de gérer l'enchaînement des actions à effectuer au cours du match, en adaptant la stratégie lorsque des problèmes sont rencontrés (route barrée par un ennemi, porte bloquée, servo qui ne répond pas...). Les actions à réaliser sont décrites dans un fichier XML, sous la forme d'un arbre de dépendances ; le scheduler les envoie progressivement aux noeuds de niveau inférieur en adaptant les requêtes suivantes en fonction des réponses reçues.

L'idée est donc de créer "l'arbre des possibles" d'un match dans le fichier de définition pour un robot précis, en précisant quelles actions sont dépendantes d'autrs pour s'exécuter etc.

Auteurs et versions

  • v0.1 (A17) : @MadeInPierre
    • Structure générale de parsing et décision
    • Gestion de modes et ordres d'exécution pour les listes
    • Support de requêtes pour des services uniquement
  • v0.2 (A17) : @Milesial
    • Support de paramètres d'envoi pour les ordres (service, action, envoi sur topic).
  • v1.0 (fin A17) : @MadeInPierre
    • Support de requêtes pour les topics et actions (mode bloquant)
    • Support de boucles for ou while dans les actionlist
    • Démarrage de la stratégie sur message de la HMI

Installation

Le noeud ne demande aucune dépendance particulière, à part rospy (librairie ROS pour python) et l'existence des noeuds auxquels les ordres inscrits sont envoyés.

Configuration

Il y a deux grands éléments à configurer pour faire fonctionner le scheduler : un dictionnaire situé dans le fichier ai_scheduler/src/scheduler_communication.py donnant les classes de messages/services/actions ROS permettant la création de clients de communication ; ainsi que les fichiers 1_strategies.xml, 2_actions.xml, 3_orders.xml situés dans memory_definitions/def/robots/<nom_du_robot>/ai/*.xml

Création des stratégies, actions et ordres du robot (fichiers XML)

La structure pour donner l'arbre des possibles au robot repose sur 4 principaux concepts :

  • Les ordres, ou order, définis dans le fichier 3_ordres.xml : Ils sont la base du scheduler. Ce sont les messages à proprement parler qui seront envoyés vers les noeuds qui tiennent les serveurs de communication.
  • Les actions, ou action, définies dans le fichier 2_actions.xml : Ce sont des listes d'order ou d'autres action existantes. Elles permettent de définir des suites d'ordres indépendantes des stratégies possibles à adopter. Par exemple, une action go_fire_balls peut-être utilisée dans plusieurs stratégies différentes ; il vaut mieux donc dfinir cette suite dans une action plutôt que dans la stratégie, car elle sera utilisable dans toutes les stratégies sans copier-coller.
  • Les listes d'actions, ou actionlist, pouvant être mises dans des action ou strategy : listes d'actions et d'ordres. C'est ici que l'on peut définir les conditions, ordres et nombre d'exécutions des actions/ordres descendantes. C'est cet outil, qui regroupe les actions/ordres en une liste, qui permettent de construire les interdépendances des éléments dans l'arbre des possibles.
  • Les stratégies, définies dans le fichier 1_strategies.xml : permettent de définir plusieurs arbres pour un même robot : ainsi, au démarrage du robot juste avant un match, on peut choisir laquelle appliquer en fonction de l'équipe qui joue contre nous ! Peut aussi juste servie pour faire des séries d'actions pour des tests. Les stratégies sont composées d'actionlist, actionref ou orderrefs.

Renseignement des topics et classes de messages au scheduler

Toutes les destinations d'ordres mises dans les fichiers XML doivent être isncrites dans le dictionnaire de ai_scheduler/src/scheduler_communication.py. Il permet ainsi à ai/scheduler d'envoyer les requêtes au système ROS (les fichiers XML ne donnant pas assez d'informations pour créer des clients de topics/services/actions). Lorsqu'il faut créer une nouvelle destination de requêtes, il suffit d'y ajouter une clé/valeur selon les règles suivantes :

  • Le nom du subscriber de topic ou serveur d'action/service, à renseigner en tant que clé du dictionnaire.
  • La valeur à y assigner est un tuple à 2 valeurs (3 dans le cas d'un serveur d'action), comportant :
    • Le type de serveur en question en première position. Le scheduler supporte les types de requêtes suivants :
      • RequestTypes.PUB_MSG : avec cette valeur inscrite, le scheduler prend la clé comme un nom de topic. A l'exécution d'un ordre ayant ce type de requête, le scheduler publie un message sur ce topic avec les paramètres donnés en XML.
      • RequestTypes.SUB_MSG : la destination fournie en clé est vue comme un nom de topic. Le scheduler attend qu'un message (ayant des paramètres quelconques pour l'instant, TODO besoin de plus ?) soit publié sur le topic par un noeud externe avant de considérer l'ordre à exécuter réussi.
      • RequestTypes.SERVICE : Le scheduler envoie une requête de service à la destination fournie en clé avec les paramètres donnés en XML. Afin que le scheduler puisse comprendre la réponse du service (et savoir si l'exécution a réussi), celui-ci doit avoir un bool success ou ai_scheduler/TaskResult result dans la réponse.
      • RequestTypes.ACTION : Le scheduler envoie une requête d'action bloquante (TODO pour l'instant) avec les paramètres inscrits dans le XML. un bool success ou ai_scheduler/TaskResult result doit exister dans la réponse.
    • La classe Python du message à envoyer à la destination. Ajouter un import mon_paquet.msg (ou .srv) en début de fichier, puis compléter le tuple :
      • Pour un topic ou service, donner la classe du message principal (e.g. drivers_ard_hmi.msg.ROSEvent ou drivers_ard_asserv.srv.SetPos)
      • Pour une action, donner en second élément du tuple la classe principale d'action (e.g. movement_actuators.msg.dispatchAction) et en troisième la classe du Goal (e.g. movement_actuators.msg.dispatchGoal).

A titre d'exemple, la classe RequestTypes du fichier scheduler_communication.py doit donc avoir une structure de la forme :

import ai_game_status.srv
import ai_scheduler.msg

class RequestTypes(object):
    PUB_MSG = 0 # Publish a message on the specified topic.
    SUB_MSG = 1 # Wait for a message to be published at the specified topic name.
    SERVICE = 2 # Sends a service request to the specified destination.
    ACTION  = 3 # Sends a blocking action request to the specified destination.

    SERVERS = None

    @staticmethod
    def init():
        RequestTypes.SERVERS = {
            "/ai/scheduler/score":        (RequestTypes.PUB_MSG, ai_scheduler.msg.AIScore),
            "/ai/game_status/set_status": (RequestTypes.SERVICE, ai_game_status.srv.SetStatus),
        }
    ...

Démarrage et exécution

Communication

Structure et fonctionnement internes

Comment que c'est codé tout ça pour que ça marche ?

DEPRECATED BELOWWWW, TOBETRASHED

Relations externes

Dépendances

Aucune dépendance extérieure autres que les paquets référencés dans la partie communication.

Communication

Serveurs :

//TODO A définir : doit pouvoir être mis dans des états globaux de match : initialisation, calibration, armement, en jeu, fin de jeu.

Client de :

  • /navigation/navigator/goto : envoie des requêtes de mouvement de la base roulante lorsqu'une action nécessite un déplacement.
  • /movement/actuators/act : envoie des requêtes de mise en position d'actionneurs pour exécuter des actions.
  • /memory/map/check : le scheduler peut demander à la map si certaines conditions sont remplies avant d'exécuter une action (réservoir de balles pas encore plein, position du robot à un certain endroit...)

Structure interne

Le noeud a un structure entièrement récursive :

Clone this wiki locally