---
# System prepended metadata

title: Organisation du code
tags: [EVOLUTEK]

---

---
title: "Organisation du code"
date: "10-12-2020"
link: "https://hackmd.io/IVKMbv5YT9SKo8zeOq5d-w"
tags: EVOLUTEK
---

# Organisation du code


## Introduction
Le code est architecturé autour de *services* [Cellaserv](https://hackmd.io/JhQ0mkRDQuGQKasJEBeDBQ) pour les robots **Evolutek<<**.

On peut distinguer deux grosses parties :
* Le code bas niveau
* Le code haut niveau, consistant principalement de services cellaserv en python.

L'ensemble du code haut niveau se trouve dans ce [Repo](https://github.com/evolutek/services).
Il existe aussi une archive des années précédentes [ici](https://github.com/evolutek/archive-services)

## Architecture


![Architecture 2021](https://i.imgur.com/v0wy14A.png)

Cette architecture comporte 5 niveaux :
* *Hardware* : matériel du robot
* *Firmware* : communication entre le logiciel et le matériel
* Services *interface* : *services* s'interfaçant avec le matériel du robot (possiblement via un service *firmware*), fournit une API cellaserv pour le matériel, mais pas de logique avancée
* *Services* agrégation : facilite le contrôle/configuration du robot
* *Services* Décision : gère la partie logique et prend les décisions pour le robot


Durant l'année 2021, nous allons essayer de rajouter un bus CAN dans le robot pour rendre le rendre plus modulaire.

![Architecture 2021 avec le bus CAN](https://i.imgur.com/Syx82QR.png)


Les schèmas sont disponnibles [ici](https://drive.google.com/file/d/1dup8jsQc7rkgrPkFdyxiAK-8poYo0ik4/view?usp=sharing).

## Code bas niveau

TODO

## Code haut niveau

Dans le repo, sur la branche *master* (branche utilisée sur les robots), nous retrouvons l'ensemble du code utilisé sur le linux des robots.

```
|-python
  |- conf.d                     # --- Configs ---
    |- ax.json                  # Config des AX12 des robots
    |- cellaserv                # Config de Cellaserv
    |- config.ini               # Config globale pour les robots
    |- *.png                    # Images utilisées pour les interfaces
    |- obstacles.json           # Config des obstacles de la table
    |- simulation.json          # Config de la simulation
    |- strategies.json          # Stratégies des robots
    |- tim.json                 # Config des Lidars TIM
  |- evolutek                   # Package Evolutek
    |- lib                      # --- Bibliothèque ---
      |- map                    # Bibliothèque pour le service map
          |- debug_map.py       # Interface de debug pour la map
          |- map.py             # Bibliothèque de gestion de la map
          |- point.py           # Bibliothèque de point
          |- tim.py             # Bibliothèque de gestion d'un TIM
          |- utils.py           # Bibliothèque d'utilitaires pour la map
      |- action_queue.py        # Bibliothèque de gestion d'actions avec une queue
      |- fsm.py                 # Bibliothèque d'automate à états finis
      |- goals.py               # Bibliothèque de gestion des objectifs du robots
      |- gpio.py                # Bibliothèque de gestion du robot
      |- interface.py           # Bibliothèque de création d'interface
      |- mdb.py                 # Bibliothèque de communication avec le MDB du robot
      |- rgb_sensors.py         # Bibliothèque de gestion des capteurs RGB TCS34725
      |- robot.py               # Bibliothèque de contrôle du déplacement du robot
      |- settings.py            # Bibliothèque de gestion des paramétres du robot
      |- watchdog.py            # Biblothéque de watchdog
    |- services                 # --- Services ---
      |- acuators.py            # Service des actionneurs du robot
      |- ai.py                  # Service de l'IA du robot
      |- ax.py                  # Services des AX12
      |- config.py              # Service de config
      |- map.py                 # Service de la map
      |- match.py               # Service du match
      |- trajman.py             # Service de communication avec la carte moteur
    |- simulation               # --- Simulateur ---
      |- fake_lib               # Fausse bibliothèque pour simuler le matériel
        |- fake_gpio.py         # Bibliothèque de faux gpios du robot
        |- fake_tim.            # Bibliothèque simulant les lidars TIM561
      |- fake_ax.py             # Services simulants les AX12 du robot
      |- fake_trajman.py        # Service simulant la carte moteur
      |- launch_enemies.py      # Script lançant tous les services pour des robots adverses
      |- launch_robot.py        # Script lançant les services d'un robot
      |- simulator.py           # Script lançant un simulateur
    |- tests                    # --- Tests ---
      |- test_gpio.py           # Test de la bibliothèque de gpios
      |- test_map.py            # Test de la biblothèque de la map
      |- test_robot.py          # Test de l'utilitaire de déplacement du robot
      |- test_tim.py            # Test de la bibliothéque pour les TIM
      TODO
    |- utils                    # --- Utilitaires ---
      |- shell                  # Shell de contrôle du robot
        |- actuators.py         # Shell des actionneurs
        |- ax.py                # Shell des AX12
        |- config.py            # Shell pour la config
        |- data_printer.py      # Bibliothèque pour afficher du JSON
        |- mdb.py               # Shell du MDB
        |- robot.py             # Shell de contrôle du robot
        |- shell.py             # Shell global
        |- shell_global.py      # Stockage des variables globales du shell
      |- ai_interface.py        # Interface de gestion de l'IA du robot
      |- diagnostic_tool.py     # Outil de diagnostic pour notre système
      |- map_interface.py       # Interface de la map
      |- match_interface.py     # Interface du match
      |- odom-_tools.py         # Outils de configuration de l'odométrie des robots
      |- tim_debug_interface.py # Interface de debug des TIM561 
    |- __init__.py              # Fichier de déclaration du package Evolutek
  |- systemd                    # Fichier Systemd des services
  |- evolutek.rules             # Régles Udev pour les robots
  |- requirements.pip           # Dépendance du package Evolutek
  |- setup.py                   # Script setuptools pour déployer le package Evolutek
```

### Configuration

#### AX

*ax.json* contient la configuration des **AX12** des robots.

Ce fichier devrait disparaître à long terme.

#### Cellaserv

*cellaserv* contient notre config du serveur et du client pour la coupe.

#### Config

*config.ini* contient la configuration de notre code.

Elle est divisée en plusieurs section :
* Ai : Section pour l'IA (à enlever)
* Avoid : Section pour l'évitement d'urgence (à enlever)
* Gpios : Section pour les gpios (à enlever)
* Tim : Section des capteurs lidars
* Map : Section de la *Map*
* Match : Section pour la gestion des matchs
* Monitor : Useless
* Tracking : Section pour le tracking des robots adverses avec les lidars (à garder ?)
* Pal : Config du robot principal
* Pmi : Config du robot secondaire

#### Map

*map.png*, image de la table de la coupe.

#### Obstacles

L'ensemble des obstacles sont stockés dans *obstacles.json*.
Ce fichier contient les obstacles fixes sur la table mais aussi les zones reservées à l'adversaires.

#### Simulation

*simulation.json* contient la configuration pour le simulateur.

#### Tim

*tim.json* contient la configuration des balises lidars utilisées pendant les matchs.

### Bibliothéque

#### Map

Cette bibliothéque permet de :
* Stocker l'état de la table pendant les matchs
* Communiquer avec les lidars TIM
* Calculer des trajectoires

##### Debug Map

Cette biblothéque met à disposition une *interface* de debug pour tester la bibliothéque de *Map*.
Elle utilise **TKinter**.

Elle permet de :
* D'afficher la table
* D'afficher les données des lidars
* D'afficher les robots détecter et les notres
* D'afficher les polygones de la tables
* D'afficher des trajectoires

Cette *interface* a besoin d'être lancé dans un thread à part avec un accès au *service de map*.

##### Map

Cette bibliothéque permet de créer un object *Map* pour stocker l'état de la table.

Elle gére tout avec des polygones de la biblitohéque **Shapely** :
* Un polygone pour les bordures de la table
* Des polygones pour chaque sur la table (décor/robots)
* Un polygone de la fusion de tous les obstacles, qui peut être un polygone multiple
* Un polygone pour la table qui correspond à l'intersection entre les bordures et les obstacles sur la table

Pour les robots, nous générons des *octogones* grâce à la lib *Planar*.

TODO pathfinding

##### Point

Permet de maniupler un objet point standard pour tout le code.

Cette classe hérite de l'objet *Point* de **Shapely**.

##### Tim

Cette classe permet de communiquer avec un *lidar* **TIM561** de chez **Sick** en utilisant une *socket TCP/IP*.

Lorsque vous créez cette classe, il va lancer un *thread* qui va envoyer récupérer les scans du capteur.

Pour calculer la position des robots vu par le capteur, le code :
* Transforme les points du nuages de coordonées polaires à cartésiennes
* Enlève les points en dehors de la table (et des obstacles un jour)
* Regroupe les points prôches
* Calcule le centre des formes détectées

De plus, le capteur conserve les différents traitement des scans pour pouvoir débug sur l'interface de débug de la *map*.

Il y a 3 modes de débug :
* Normal : Permet de voir le centre des robots détectés fusionnés
* Debug Merge : Permet de voir en plus le centre des robots non fusionnés
* Debug Tim : Permet de voir les scans bruts

##### Utils

Contient des utilitaires pour la bibliothéque de la *map* :
* Parsing des obstacles
* Utilitaires sur les polygones
* Algorithmes de pathfinding
* Conversion des trajectoires pour les sérialiser

#### Goals

Cette bibliothéque permet de gérer les objectifs et stratégies du robot stockés dans des fichiers JSON.

TODO Décrire la gestion des objectifs

#### Gpio

TODO

#### Match Interface

C'est une interface de débug pour le service de match.
Elle utilise **TKinter**.

Elle permet de :
* Choisir la couleur du match
* Affiche la table
* Affiche la position des robots
* Affiche le status de nos robots
* Affiche l'état du match
* Affiche le score à la fin du match

#### Robot

Permet de contrôller le déplacement du robot plus facilement qu'en utilisant le service *Trajman* directement.

Pour gérer les déplacements, nous décorons les fonctions de *Trajman* de cette façon :
* Lance un *Watchdog de 1s*
* Lance la fonction de déplacement
* Attend que l'*event* de démarrage du déplacement (*'ROBOT_started'*)
* Quitte si l'évenement n'est pas apparu à la fin du *watchdog*.
* Attend que l'*event* de fon de déplacement (*ROBOT_stopped*)

Comme *Trajman*, gére maintenant l'évitement d'urgence, cette biblothéque renvoie un status du mouvement pour indiquer si l'on a réussi ou raté le déplacment :
* Reached : Le robot a atteind son objectif
* Unreached : le robot n'a pas atteind son objectif
* Has Avoid : le robot a évité un obstacle
* Unreachable : l'objectif est inaténiable (ici on utilise le *pathfinding*)

La gestion de l'inversion des coordonées pour le robot selon la couleur de l'équipe se fait dans cet utilitaire.

#### Settings

Cet utilitaire nous permet de configurer certains paramètres :
* ROBOT : nom du robot sur lequel le code tourne
* SIMULATION : indique si on est en simulation

#### Watchdog

Un *watchdog* est un *timer* qui appelle une fonction à la fin du décompte.

Il fonctionne ainsi :
* Création du *watchdog*  avec un temps de décompte et une fonction à appeler
* Lancement du *watchdog*
* On peut relancer le *watchdog* à 0 avant qu'il ne soit au bout du décompte
* A la fin du décompte, il appelle la fonction fournie

### Services

Comme ce sont des *services* tournant sur **Cellaserv**, il faut retenir que le code de gestion des *actions* et des *events* du robot tourne dans un *thread* 

#### Actuators

*Service* des actionneurs du robot. Ce *service* nous permet de coder les fonctions du robot pour effectuer des actions lors des matchs.

Le *service* peut bloquer l'utilisation une des ses fonctions si l'utilisateur le souhaite (via *enable() et disable()*).
Cette fonctionnalité nous permet notemment de désactiver une parti des fonctionnalités du robot à la fin du match.

TODO Déscritption du fonctionnement avec une queue.

#### AI

Ce *service* prend les décisions de ce que va faire le robot pendant ses matchs.

Il fonctionne via une *machine à état* qui permet de plus facilement débugger le comportement du robot.

La machine à état est décrite sur ce [Diagramme](https://drive.google.com/file/d/1_bMraeyNdjSzCrgwyiRk-Fbrm7IK8_Ku/view?usp=sharing).

TODO : référence vers la page HACKMD

#### AX

Ce *service* est un poil spécial. Ici on définie un service qui permet de communiquer avec un **AX12** en utilisant la *USB2AX* connecté à un ordinateur sur *Linux*.

Un **AX12** est un servo-moteur intélligent dont nous sommes fans à **Evolutek<<**.

On va venir lancer un service par AX12 pour pouvoir communiquer à plusieurs **AX12** à la fois.

#### Config

Ce *service* sert à avoir une configuration disponnible sur **Cellaserv**.
Au démarrage, il va ouvrir un fichier (*/etc/conf.d/config.ini*) contenant notre configuration pour tous le code d'**Evolutek<<**.

#### Map

Ce *service* utilise la bibliothéque eponyme pour stocker l'état de la table pendant les matchs.

Ce service va :
* Gérer les capteurs lidars dans un *thread*
* Permettre de calculer des trajectoires pour les robots

#### Match

Ce *service* gére le match. Il permet notamment de :
* Lancer le match
* Compter le score
* Gérer la couleur
* Stocker des informations pour débug

Il lance notamment l'interface de débug dans un *thread* si l'option est activée.

#### Trajman

*Trajman* pour *trajectory manager*, nous permet de communiquer avec la carte moteur via une *liaison serie*. 

Cette carte permet de déplacer le robot via deux moteurs *DC*. Pour connaître sa positon, le robot posséde deux roules folles montées sur des encodeurs de chaque côté du robot qui suivent 

De plus, le *service* gère l'évitement d'urgence du robot; c'est à dire qu'il regarde les capteurs de proximité du robot pour l'arrêter avant une collision avec un obstacle.

Voici comment le *service* fonctione :
* Un *thread* s'occupe de lire les retours de la carte sur la lisaion série et les envoie au serveur.
* Un autre *thread* lit les capteurs et arrête le robot s'il se dirige vers un obstacle.

### Simulation

TODO