Bienvenue sur la page du projet de MT3

Objectif du projet: découvrir ROS2

Sommaire:

  1. Quelques concepts de ROS2
  2. Liste du matériel
  3. Les étapes du challenge MT3
  4. Les contraintes et ce qui est évalué
  5. Les dates de projet
  6. ESP32 et sa vidéo
  7. Tâches à effectuer sur l'ESP32
  8. ROS2 et sa vidéo
  9. Vidéo de démonstration
  10. Tâches à effectuer sur la partie ROS2

Quelques concepts de ROS

La distribution ROS2 est jazzy (echo $ROS_DISTRO)

  • Les nodes: Chaque noeud dans ROS doit être responsable d'une seule tâche (par exemple, commander les moteurs de roue ou publier une image de caméra).
    -> Pour lister les noeuds: ros2 node list
    ou, pour avoir plus d'infos: ros2 node info <node_name>
  • Les topics: Les topics sont un élément essentiel dans ROS: ils jouent le rôle d'un bus permettant aux noeuds d'échanger des messages.


    Un nœud peut publier des données sur un nombre quelconque de topics et, simultanément, être abonné à un nombre quelconque de topics

    Pour lister les topics: ros2 topic list
    ou avec plus d'informations ros2 topic list -t
    Pour voir les informations d'un topic en particulier: ros2 topic info
    Pour voir les données publiées sur un topic: ros2 topic echo <topic_name>
  • rqt_graph est un utilitaire très important pour observer les nodes et les topics

Liste du matériel sur le robot:

Liste du matériel commun:

  • Caméra en douche connectée sur un PC
  • Node accessible

 


Présentation du Projet Robotique

Objectif général

Chaque binôme devra concevoir, programmer et tester un robot autonome capable de se déplacer de manière intelligente sur un parcours défini.

Contexte commun

  • Tous les binômes utilisent le même matériel et travaillent sur la même plateforme de développement.

  • Le projet est progressif : vous développerez votre robot par étapes successives, en ajoutant des fonctionnalités à chaque phase.

Le schéma de principe:

 


Les 3 Étapes du Challenge MT3

🟢 Étape 1 : Parcours libre

Objectif : Aller le plus rapidement possible d'une zone de départ vers une zone d’arrivée, sans obstacle et sans intervention humaine.

  • Première prise en main du robot.

  • Mise en place de la navigation de base.

  • Analyse du parcours et optimisation de la trajectoire.


🟡 Étape 2 : Parcours avec obstacles

Objectif : Aller le plus rapidement possible d'une zone de départ vers une zone d’arrivée, avec des obstacles fixes, sans intervention humaine.

  • Implémentation de la détection d’obstacles (capteurs).

  • Algorithmes d’évitement.

  • Adaptation dynamique de la trajectoire.


🔴 Étape 3 : Parcours avec concurrence

Objectif : Aller le plus rapidement possible d'une zone de départ vers une zone d’arrivée, avec obstacles et en présence d’un robot concurrent.

  • Capacité à s’adapter à un environnement dynamique.

  • Anticipation des mouvements d’un autre robot.

  • Gestion de priorités, trajectoires partagées, et compétition.


Contraintes et Évaluation

  • Aucun contrôle manuel pendant les phases de test.
  • ROS2 obligatoire
  • Respect des consignes de sécurité et des règles de la plateforme.
  • L’évaluation prendra en compte :
    • Les performances (vitesse, fiabilité)
    • L’intelligence du comportement (adaptabilité, prise de décision)
    • La rigueur du développement (propreté du code, tests, documentation)
    • Le design du robot: humour, frayeur, originalité, ....
    • Un poster A3 de présentation du robot et de sa programmation
    • Une vidéo de démonstration de moins de 2 minutes

Dates des projets MT3 (24h)

  • Mardi 6 mai AM:
    1/ venir votre PC et avec la VM qui fonctionne (et avec les add-ons installés)
    2/ objectif 1: Commander les moteurs avec une rampe d'accélération et de décélération
  • Mercredi 7 mai PM
    3/ objectif 2: se connecter sur le noeud de vision
    4/ objectif 3: générer une trajectoire entre un point A et un point B
  • Mercredi 14 mai AM + PM
    5/ objectif 4: le robot va du point A au point B seul
    6/ objectif 5: la vision traite les obstacles
    7/ objectif 6: le robot va du point A au point B, en évitant les obstacles, seul.
  • Jeudi 27 mai AM + PM
    8/ AM: Tests et homologations
    9/ PM: Compétitions
  • Dimanche 8 juin à minuit:
    10/ Rendu du travail

Notes ESP32 WROOM 32D:

Attention au cablage: plusieurs broches bloquent la programmation... Regardez la datasheet.

Le document de référence de l'ESP32 est ici

  1. Prendre ESP32 DEV MODULE, vitesse de transfert de 115200  et Flash mode: DIO
  2. Les broches 21 (I2C Clock) et 22 (I2C Data) seront utilisées pour l'afficheur
  3. Connecter les servomoteurs sur GPIO 0 et GPIO 2 pour les "data" des 2 servomoteurs.
  4. Le +5V à coté de l'USB.
  5. Le GND, entre le GPIO12 et GPIO13.

Le programme que j'ai utilisé pour l'ESP32:

#include <WiFi.h>
#include <ESP32Servo.h>
#include <micro_ros_arduino.h>

#include <rcl/rcl.h>
#include <rclc/rclc.h>
#include <rclc/executor.h>
#include <geometry_msgs/msg/twist.h>

// pour le LCD I2C
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2); // 0x27 est l'adresse I2C de mon afficheur

// Paramètres Wi-Fi
const char* ssid = "Snoecksansfil ";
const char* password = "gondreville";

// Micro-ROS Agent (adresse IP du PC avec ROS2)
const char* agent_ip = "192.168.1.75";
const uint16_t agent_port = 8888;


#define nullptr NULL
const int NiveauHautMaximum=2500;
const int NiveauHautMinimum=500;
const int NiveauHautArret=1500;
int NiveauHaut = NiveauHautArret;

// Servos (GPIO)
Servo servo_gauche;
Servo servo_droite;
const int pin_servo_gauche = 16;
const int pin_servo_droite = 17;

// Paramètres servo
const int angle_stop = 90; // angle neutre (arrêt)
const int angle_max_forward = 120;
const int angle_max_backward = 60;

// ROS2
rcl_subscription_t subscriber;
geometry_msgs__msg__Twist msg;
rcl_node_t node;
rclc_support_t support;
rcl_allocator_t allocator;
rclc_executor_t executor;

// Callback : réception d'un cmd_vel
void cmd_vel_callback(const void * msgin) {
const geometry_msgs__msg__Twist * msg = (const geometry_msgs__msg__Twist *)msgin;

Serial.print("Reçu cmd_vel: lin=");
Serial.print(msg->linear.x);
Serial.print(" ang=");
Serial.println(msg->angular.z);
float linear = msg->linear.x; // Avant / Arrière (-1 à 1)
float angular = msg->angular.z; // Rotation (-1 à 1)

// Calcul des angles servo (différentiel)
int moteur_gauche = NiveauHautArret + (linear * 1500) + (angular * 1500);
int moteur_droite = NiveauHautArret + (linear * 1500) - (angular * 1500);

// Contraintes sécurisées des angles
if (moteur_gauche >= NiveauHautMaximum){moteur_gauche = NiveauHautMaximum;}
if (moteur_gauche <= NiveauHautMinimum){moteur_gauche = NiveauHautMinimum;}
if (moteur_droite >= NiveauHautMaximum){moteur_droite = NiveauHautMaximum;}
if (moteur_droite <= NiveauHautMinimum){moteur_droite = NiveauHautMinimum;}

servo_gauche.write(moteur_gauche);
servo_droite.write(moteur_droite);
Serial.print("moteur_gauche ");
Serial.println(moteur_gauche);
Serial.print("moteur_droite ");
Serial.println(moteur_droite);
}

void setup() {
//initialisation de la liaison série pour le moniteur série
Serial.begin(115200);
//Initialisation de l'afficheur LCD
Wire.begin();
lcd.init(); // Initialisation de l'écran
lcd.backlight(); // Active le rétroéclairage
lcd.setCursor(2, 0);
lcd.print("Mecatronique");
lcd.setCursor(6, 1);
lcd.print("MT3");

// Initialisation servos
servo_gauche.attach(pin_servo_gauche, 500, 2400);
servo_droite.attach(pin_servo_droite, 500, 2400);
servo_gauche.write(angle_stop);
servo_droite.write(angle_stop);
Serial.println("Les servos sont initialiasés");
// Connexion au Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("Le WiFi est KO: attente");
lcd.init();
lcd.setCursor(2, 0);
lcd.print("Mecatronique");
lcd.setCursor(4, 1);
lcd.print("WiFi KO");
}
Serial.println("Le WiFi est OK");
lcd.init();
lcd.setCursor(2, 0);
lcd.print("Mecatronique");
lcd.setCursor(4, 1);
lcd.print("WiFi OK");
delay(1000);

Serial.println(WiFi.localIP());
// Micro-ROS (Wi-Fi UDP)
lcd.setCursor(0, 1);
lcd.print(WiFi.localIP());
set_microros_wifi_transports(
(char*)ssid, (char*)password, (char*)agent_ip, agent_port
);

delay(2000); // Stabilisation transport

// Initialisation ROS2
allocator = rcl_get_default_allocator();
rclc_support_init(&support, 0, NULL, &allocator);
rclc_node_init_default(&node, "esp32_diffdrive", "", &support);

rclc_subscription_init_default(
&subscriber, &node,
ROSIDL_GET_MSG_TYPE_SUPPORT(geometry_msgs, msg, Twist),
"/cmd_vel"
);

rclc_executor_init(&executor, &support.context, 1, &allocator);
rclc_executor_add_subscription(
&executor, &subscriber, &msg, &cmd_vel_callback, ON_NEW_DATA
);
Serial.println("Fin du setup");
lcd.setCursor(0, 0);
lcd.print("- Mecatronique -");
}

void loop() {
rclc_executor_spin_some(&executor, RCL_MS_TO_NS(100));
}
 
 
Tâches à effectuer sur l'ESP32:
  1. Afficher des messages dans le moniteur série:
    "Les servos sont initialiasés" + "Le WiFi est KO: attente" + "Le WiFi est OK" + "Fin du setup"
  2. Ajouter un afficheur LCD i2c (attention, il faut revoir la connectique complètement)
  3. Afficher les mêmes messages sur l'afficheur LCD i2c (état de la connexion et issus du topic cmd_vel)
 

Partie ROS2

Sur la VM de M.Blazevic, j'active la connection avec micro-ros:
ros2 run micro_ros_agent micro_ros_agent udp4 --port 8888
 
sur un autre onglet du terminal (Ctrl + shift + T), je vérifie si le topic existe: ros2 topic list
Je n'obtiens rien d'interessant:
/parameter_events
/rosout
 
Je publie le topic sur un autre onglet: ros2 topic pub /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.0}, angular: {z: 0.0}}"
linear=0 -> on est arrêté
 
Je reviens sur mon onglet où je vois les topic et je recommence: ros2 topic list
Et là, cela commence à être interessant: Le topic /cmd_vel est le topic de "command velocity".
/cmd_vel
/parameter_events
/rosout
 
Je reviens sur l'onglet de la publication et je modifie les données:
Pour avancer: ros2 topic pub /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 1.0}, angular: {z: 0.0}}"
Pour reculer: ros2 topic pub /cmd_vel geometry_msgs/msg/Twist "{linear: {x: -1.0}, angular: {z: 0.0}}"
Pour arrêter: ros2 topic pub /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.0}, angular: {z: 0.0}}"
 
 
ros2 topic info /cmd_vel permet de connaitre le type de topic (ici, geometry_msgs/msg/Twist), le nombre de "publisher" et le nombre de subscriber"
 
 

Tâches à effectuer sur la partie ROS2:

  1. commander les 2 servomoteurs à partir des touches de votre clavier
  2. commander les 2 servomoteurs à partir d'une manette de jeu