Tag: robot

IA – Neurone artificiel avec le robot MR25 (Partie 1)

Présentation

Dans cet article nous allons apprendre au robot MR25 à éviter les obstacles en utilisant un neurone perception. Le perceptron est le neurone artificiel le plus simple, modèle de neurone biologique, il a été inventé en 1957 par Frank Rosenblatt au laboratoire d’aéronautique de l’université Cornell. Ce neurone reçoit plusieurs entrées, les combine avec des poids, puis prend une décision binaire.

Intelligence artificielle avec le robot MR25

Voici un exemple simple de neurone perceptron à 2 entrées utilisant les capteurs de proximité n°2 et n°4 du MR25.

Voici le principe de fonctionnement :

Entrées du neurone (capteurs de proximité) :

    • x1 = proxSensor(2)
    • x2 = proxSensor(4)

Sortie du neurone :

      • 0 → arrêt du robot
      • 1 → avance du robot

Le calcul effectué par le neurone est :

Avec :

  • : valeur du capteur 2
  • x2 : valeur du capteur 4
  • w1 : poids associé au capteur 2
  • w2 : poids associé au capteur 4
  • b : biais du neurone
  • s : somme pondérée

Ensuite, une fonction d’activation à seuil décide de la sortie du neurone :

Le perceptron est entraîné avec quelques exemples :

  • obstacle proche → stop le robot
  • espace libre → avancer le robot

-> Si les deux capteurs détectent un espace libre (valeurs élevées), la somme est grande alors le robot avance.

-> Si un obstacle est proche (valeur faible), la somme diminue → le robot MR25 s’arrête.

Le Programme

# Macé Robotics
#
#!/usr/bin/python3
import MR25
import time

# -----------------------------
# Fonctions du perceptron
# -----------------------------

def activation(x):
"""
Fonction d'activation de type seuil (step function).
Retourne 1 si x >= 0 (avancer), sinon 0 (stopper).
"""
if x >= 0:
return 1
return 0

# -----------------------------
# Initialisation des poids et biais
# -----------------------------
# w1 : poids associé au capteur 2 (x1)
# w2 : poids associé au capteur 4 (x2)
# b : biais du perceptron (décalage du seuil de décision)
w1 = 0.0
w2 = 0.0
b = 0.0

# Taux d'apprentissage : contrôle la vitesse de correction des poids
# Une valeur trop grande peut rendre l'apprentissage instable
eta = 0.1

# -----------------------------
# Jeu d'apprentissage (données d'entraînement)
# -----------------------------
#
# x1 = capteur de proximité 2 (distance normalisée entre 0 et 1)
# x2 = capteur de proximité 4 (distance normalisée entre 0 et 1)
#
# Normalisation : 0 = obstacle très proche, 1 = espace libre
#
# Sortie attendue :
# 0 = STOP (obstacle détecté, distances faibles)
# 1 = AVANCE (voie libre, distances élevées)
training_data = [
([0.1, 0.1], 0), # Obstacle très proche sur les deux capteurs → STOP
([0.2, 0.3], 0), # Obstacle proche → STOP
([0.3, 0.2], 0), # Obstacle proche → STOP
([0.8, 0.8], 1), # Espace libre sur les deux capteurs → AVANCE
([0.7, 0.9], 1), # Espace majoritairement libre → AVANCE
([0.9, 0.7], 1), # Espace majoritairement libre → AVANCE
]

# -----------------------------
# Phase d'apprentissage (entraînement du perceptron)
# -----------------------------
# On répète jusqu'à 100 époques (passages complets sur le jeu d'entraînement)
# L'apprentissage s'arrête prématurément si tous les exemples sont bien classés
for epoch in range(100):
erreur_totale = 0 # Compteur d'erreurs pour cette époque

for inputs, target in training_data:
x1, x2 = inputs

# Calcul de la sortie du perceptron : combinaison linéaire + activation
y = activation(w1*x1 + w2*x2 + b)
print("Y = ", y)

# Calcul de l'erreur : différence entre la sortie attendue et la sortie calculée
erreur = target - y

# Mise à jour des poids selon la règle d'apprentissage du perceptron
# Si erreur = 0 : pas de modification
# Si erreur = +1 : poids augmentés (le perceptron devait dire 1)
# Si erreur = -1 : poids diminués (le perceptron devait dire 0)
w1 += eta * erreur * x1
w2 += eta * erreur * x2
b += eta * erreur # Le biais est mis à jour sans facteur d'entrée
print("w1, w2 = ", w1, w2)

# Accumulation de l'erreur absolue sur cette époque
erreur_totale += abs(erreur)
print("Erreur totale = ", erreur_totale)

# Convergence atteinte : tous les exemples sont correctement classés
if erreur_totale == 0:
break

# Affichage des poids finaux après l'apprentissage
print("Apprentissage terminé")
print("w1 =", w1)
print("w2 =", w2)
print("b =", b)

# Pause avant de démarrer le pilotage (laisse le temps de lire les résultats)
time.sleep(5)

# -----------------------------
# Pilotage du robot MR25 en temps réel
# -----------------------------

# Distance maximale prise en compte (en mm)
# Au-delà de SEUIL_MAX, la distance est considérée comme maximale (voie libre)
SEUIL_MAX = 80.0 # mm

try:
while True:
# --- Lecture des capteurs de proximité ---
# proxSensor retourne une distance en mm
x1 = MR25.proxSensor(2) # Capteur 2
x2 = MR25.proxSensor(4) # Capteur 4

# --- Normalisation des distances dans l'intervalle [0, 1] ---
# min(x, SEUIL_MAX) écrête les valeurs supérieures au seuil
# La division ramène la valeur entre 0 et 1
x1 = min(x1, SEUIL_MAX) / SEUIL_MAX
x2 = min(x2, SEUIL_MAX) / SEUIL_MAX

# --- Inférence : décision du perceptron ---
# Utilise les poids appris pour décider d'avancer ou de s'arrêter
sortie = activation(w1*x1 + w2*x2 + b)

# --- Exécution de la commande moteur ---
if sortie == 1:
MR25.forward(40) # Avance à 40% de vitesse
print("AVANCE")
else:
MR25.stop() # Arrêt immédiat
print("STOP")

# Fréquence de rafraîchissement : 10 Hz (une décision toutes les 100 ms)
time.sleep(0.1)

except KeyboardInterrupt:
# Arrêt propre du robot lors d'une interruption clavier (Ctrl+C)
MR25.stop()

# end of file

La vidéo

Ce neurone perceptron constitue la base des réseaux de neurones : un réseau plus complexe n’est qu’un assemblage de nombreux perceptrons connectés entre eux.

Les améliorations

Le perceptron à 2 entrées est un bon point de départ, mais pour ce robot il existe plusieurs améliorations possibles. Voici quelques idées :

  • Ajouter les autres capteurs n°1, 3 et 5

Un neurone à 5 entrées permettrait une meilleure perception :

  • Ajouter les déplacements comme tourner à droite ou à gauche.

Par exemple :

  • Si obstacle à droite → Alors tourner à gauche
  • Si obstacle à gauche → Alors tourner à droite
  • Si voie libre → Alors avancer
  • Ajouter la valeur réels des capteurs 

L’exemple précédent utilise un simple seul binaire qui fait perdre beaucoup d’information.

On peux faire dépendre la vitesse du robot de la sortie du neurone :

vitesse = int(sortie * 50)
MR25.forward(vitesse)

Le robot MR25 ralentit lorsqu’il y a un obstacle.

  • Utiliser une fonction sigmoide comme fonction d’activation

La fonction d’activation précédent permet d’avoir une sortie binaire.

Avec cette fonction on obtient une probabilité en sortie du neurone :

Les déplacements du robot devient beaucoup plus fluide.

  • Utiliser un petit réseau de neurone

Au lieu d’utiliser un seul neurone, utiliser :

  • neurone 1 : obstacle à gauche
  • neurone 2 : obstacle devant
  • neurone 3 : obstacle à droite

Puis un neurone de décision choisit l’action :

  • Avancer
  • Tourner gauche
  • Tourner droite
  • Stop

Pour le MR25 équipé de 5 capteurs de proximité, l’amélioration la plus efficace est généralement : 5 entrées + 3 sorties (gauche, avance, droite) + apprentissage automatique des poids. Cela permet déjà d’obtenir un véritable comportement d’évitement d’obstacles basé sur un réseau neuronal simple.

A vous de jouez !

 

Avancer vers un but avec gestion des obstacles

Un programme python pour faire avancer le robot MRPiZ vers un but avec la prise en compte des obstacles.

#!/usr/bin/env python
# Mace Robotics

from mrpiZ_lib import *
import time

# erreur odometrie
error_odo = 20

# sleep 2 secondes
time.sleep(2)

# but en millimetre
goal_robot = 200

# activer controle
controlEnable()

# lecture du capteur avant
sensor_p3 = proxSensor(3)

# lecture position du robot (axe X)
position_robot = robotPositionX()

distance_robot = goal_robot

while (position_robot < goal_robot-error_odo):
  forwardmm(10,distance_robot)# avancer vers le but
  sensor_p3 = proxSensor(3)# lecture capteur
  time.sleep(0.2) # pause 200 ms
  position_robot = robotPositionX()# lecture position robot
 
  # si obstacle 
  if (sensor_p3 < 100):
    stop()# arret du robot
    distance_robot = goal_robot - position_robot # erreur sur la distance


#end

Partie 1 : OpenCV et le robot MRPiZ

Ce tutoriel permet de faire du traitement d’images avec le robot MRPiZ en langage Python.

OpenCV_Logo

Le matériel nécessaire pour le tutoriel :

  • Un robot MRPiZ
  • Un support caméra pour le robot MRPiZ
  • Une caméra Raspberry Pi 8MP

Installation

La première étape est d’installer la camera sur la carte Raspberry Pi :

  • Installation de la camera Raspberry Pi 8MP : ici
  • Mise à jour du système:
sudo apt-get update
sudo apt-get upgrade
  • Installation de la bibliothèque de traitement d’image OpenCv :
sudo apt-get install python-opencv
  • Installation de imutils:
sudo easy_install pip
sudo pip install imutil
sudo apt-get install python-picamera python3-picamera

Une simple photo

Prendre une simple photo avec la camera et l’enregistrer dans une image, voic

#!/usr/bin/python
import picamera

camera = picamera.PiCamera()

# initialisation de la resolution
camera.resolution = (1920, 1080)

# capture d'une image
camera.capture('image.jpg')

Simple photo

Lecture d’une image

Un script pour la lecture d’une image avec OpenCv :

#!/usr/bin/python
import picamera
import cv2

camera = picamera.PiCamera()

# initialisation de la resolution
camera.resolution = (100, 100)

# capture d'une image
camera.capture('image.jpg')

image = cv2.read('image.jpg')

print image

Conversion en HSV

Conversion colorimétrique.

HSV : Hue Saturation Value

#!/usr/bin/python
import picamera
import cv2

camera = picamera.PiCamera()

# initialisation de la resolution
camera.resolution = (1920, 1080)

# capture d'une image
camera.capture('image.jpg')

# lecture de l'image
frame = cv2.imread('image.jpg')


# conversion RGB en HSV de l'image
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

# enregistrer image hsv
cv2.imwrite('image_hsv.png', hsv)

image HSV

 

 

Fin de la première partie.

Utiliser un capteur ultrason HC-SR04

Ce tutoriel présente l’utilisation du capteur HC-SR04 avec la carte Esus.

image_hc-sr04

Carte Esus + HC-SR04

Le câblage

Les caractéristiques techniques du capteur  HC-SR04  sont les suivantes :

  • Alimentation +5V
  • Consommation : 15 mA
  • Gamme de distance : 2 cm à 4 m.
  • Sortie : TTL

Pins du capteur:

  • VCC => sur + 5V de la carte Esus
  • Trig => sur IO2
  • Echo => sur IO3
  • GND => GND

Voici le schéma de câblage :

 

cablage_hc_sr04_v2Le capteur ultrason HC-SR04 fonctionne par l’envoi d’une impulsion sur la pin ‘Trig‘, puis un signal impulsionnelle est retourné sur la pin ‘Echo’ en fonction de la distance d’un obstacle. La durée de cette impulsion représente la distance de l’obstacle.

Distance en cm = ( durée de l’impulsion ‘Echo’ en µs ) / 58

signal_ultrason

Le programme en Arduino

#include <esusBoard.h>

// pins 
#define trig_pin 2
#define echo_pin 3

void setup() 
{
 // init de la carte Esus
 initEsusBoard();

 // init liaison serie
 Serial.begin (9600);
 
 // init pin trig en sortie
 pinMode(trig_pin, OUTPUT);

 // init pin echo en entrer
 pinMode(echo_pin, INPUT);

 // init pin trig à l'état bas
 digitalWrite(trig_pin, LOW);

}

void loop() 
{  
long durer;
long distanceCm;  

  // mise à l'état haut de la pin trig
  digitalWrite(trig_pin, HIGH);
  
  // pause de 10µs
  delayMicroseconds(10);

  // mise à l'état bas de la pin trig
  digitalWrite(trig_pin, LOW);
  
  // mesure de la durée du niveau haut du signal echo
  durer = pulseIn(echo_pin, HIGH);
  
  // conversion de la durer en cm
  distanceCm = (durer/58);  

  // envoi sur le port série de la distance
  Serial.print("distance= "); 
  Serial.print(distanceCm);  
  Serial.println("cm"); 
 
  // pause 1 seconde
  delay(1000);
}

Le résultat

result_ultrason

Attention, pendant le téléchargement la pin IO3 doit être débrancher du capteur, car le téléchargement à besoin de cette pin (RX/IO3).

Fin du tuto !

Contrôle d’un robot avec un smartphone

Développeur>Tutoriels>Contrôle d’un robot avec un smartphone

Un tutoriel pour contrôler un robot avec l’aide d’un smartphone sous Android.

esus_robot_phone

Le Programme la carte Esus

Voici le programme pour le microcontrôleur ESP8266 :

#include <ESP8266WiFi.h>
#include <esusBoard.h>
 
const char* ssid = "yout_SSID";
const char* password = "your_PASSWORD";

// serveur
WiFiServer server(80);

// adresse IP
IPAddress ip(192, 168, 1, 13); 
IPAddress gateway(192,168,1,1);
IPAddress subnet(255,255,255,0); 
 
void setup() 
{

  // initialisation de la carte Esus
  initEsusBoard();

  // initialisation du port serie
  Serial.begin(115200);
  delay(10);
 
  // Connection au reseau wifi
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
 
  WiFi.begin(ssid, password);
  WiFi.config(ip, gateway, subnet);

  // attendre la connexion
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  // la carte Esus est connecter au reseau wifi
  Serial.println("");
  Serial.println("WiFi connected");
 
  // Démarrage du serveur
  server.begin();
  Serial.println("Server started");
 
  // Affichage de l'adresse IP sur le port serie
  Serial.print("Use this URL to connect: ");
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  Serial.println("/");
 
}
 
void loop() 
{
  
  // vérification si un client est connecté
  WiFiClient client = server.available();

  // attendre la connexion d'un client
  while(client != true)
  {
    client = server.available();
    Serial.println("Attendre client...");
    delay(100);
  }
 
  // Un client est connecté
  Serial.println("new client");
  while(!client.available()){
    delay(1);
  }

  // lecture de la requete du client
  String request = client.readStringUntil('\r');
  
  Serial.println(request);
  client.flush();

  // commande avancer
  if (request.indexOf("/CMD=FOR") != -1) 
  {
    Serial.println("forward");
    motors1_set(1023,DIR_BACK);
    motors2_set(1023, DIR_BACK);
  }

  // commande reculer
  if (request.indexOf("/CMD=BAK") != -1) 
  {
    Serial.println("back");
    motors1_set(1023,DIR_FORWARD);
    motors2_set(1023, DIR_FORWARD);
  }

  // commande tourner a droite
  if (request.indexOf("/CMD=TR") != -1) 
  {
    Serial.println("turn right");
    motors1_set(1023,DIR_BACK);
    motors2_set(1023, DIR_FORWARD);
  }

  // commande tourner a gauche
  if (request.indexOf("/CMD=TL") != -1) 
  {
    Serial.println("turn left");
    motors1_set(1023,DIR_FORWARD);
    motors2_set(1023, DIR_BACK);
  }

  // commande tourner stop
  if (request.indexOf("/CMD=STP") != -1) 
  {
    Serial.println("turn left");
    motors1_set(0,DIR_FORWARD);
    motors2_set(0, DIR_BACK);
  }

  Serial.println("Client disonnected");
  Serial.println("");
 
}
  • Modifier votre SSID et password :
const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";
  • Ensuite vous pouvez compiler et télécharger le programme dans la carte Esus.

L’application Android

Maintenant, nous allons réaliser l’application Android grâce à App Inventor développé par Google et basée sur une interface graphique similaire à Scratch.

cr_1

  • Vous devez arriver sur l’interface de votre application :

app3

  • Alignement horizontal de l’interface : centrer

app4

  • Ajouter un bouton :

app5

  • Modifier le texte du bouton : AVANCER
  • Ajouter d’autres boutons avec :

    • RECULER
    • DROITE
    • GAUCHE
  • Utiliser la disposition en tableau avec 3 colonnes et 3 lignes :

cr_2

  • Ajouter l’Afficheur Web :

cr_3

  • Rendre l’afficheur web non visible

Réalisation des blocs :

  • Voici le programme en bloc pour la gestion des boutons :

cr_5

Construction de l’application

  • Construction de l’application sur votre ordinateur :

app10

  • Transférer l’application sur votre smartphone.
  • Autoriser l’installation de l’application sur votre téléphone.

MRduino à l’Euro 2016 !

Le robot MRduino joue au football pour l’Euro 2016.

MRduino est équipé d’un bras avec deux servomoteurs SG90 :

  • Alimentation des servomoteurs avec le +BATT

FootEuro2016

Vidéo :

 

Le programme :

#include <Servo.h>
#include <mrduino.h>

Servo Servo1;
Servo Servo2;

int reception;
 
void setup()
{
    Servo1.attach(2, 1000, 2000);
    Servo2.attach(4, 1000, 2000);

    Servo1.write(90);
    Servo2.write(180);

    delay(500);

    Serial.begin(115200);
}

void loop() {


   // read IR reception sensor
  reception = irReceiver();

  // read command
  switch(reception)
  {
    case 2:
      forward(30);// Forward
    break;

    case 6:
      turnRight(30);// turn right
    break;

    case 4:
      turnLeft(30);// turn left
    break;

    case 8:
      back(30);// back
    break;

    case 5:
      stop();// stop
    break;

    case 7:
     Servo1.write(160);
     Servo2.write(90);
    break;

    case 9:
     Servo1.write(90);
     Servo2.write(180);
    break;
  }


}