Transformée en Cosinus Discret d’une image

Introduction

La transformée en Cosinus Discret aussi connue sous l’abréviation de DCT et une opération très connue dans le domaine du traitement d’image qui permet de passer de la représentation spatial d’un signal à une représentation spectrale de celui-ci.

La DCT est proche de  la transformée de Fourier, mais possède des propriétés intéressantes qui la rendent parfois plus adaptée à certaines opérations de traitement du signal et notamment de l’image. Ces trois propriétés de base sont  :

  • Transformée à coefficient réels (simple à calculer).
  • Transformation sans pertes (le signal orignal peut être retrouvé à l’identique par transformée inverse).
  • Concentration de l’information dans les coefficients de basse fréquence.

Du fait de son aptitude à concentrer l’information d’un signal réel dans les coefficients de basse fréquence, la DCT peut être utilisée dans des opérations de compression de l’information. A ce propos la DCT est une des étapes clef de la compression d’images au format JPEG.

Nous présentons dans cet article comment calculer la DCT et la DCT inverse sur un signal en deux dimensions . La programmation à été réalisée en langage C avec les bibliothèques standard du langage C.

Théorie et précisions

Tout d’abord voici les formules de la DCT et de l’IDCT pour un signal en 2 dimensions (typiquement une image) :

Formule DCT2
DCT 2D
idct2
IDCT 2D

Avec :

  • n et m, la largeur et la hauteur de l’image en pixel (ex  n=512 m=512).
  • C(u) et C(v) les facteur d’orthogonalité de la transformée  :cu
  • I(x,y) la valeur du pixel de l’image a transformer à la position x et y.
  • F(u,v) correspond au coefficient de la transformée.

On constate que ces formules amènent une quantité non négligeable de calculs, par exemple dans le cas d’une image de 512*512 pixels il faut au minimum calculer 512² multiplications. C’est pourquoi dans les application de base il est plus commode de découper l’image en petit morceaux pour ensuite appliquer la DCT sur chacun de ces morceaux séparément. Le format JPEG se base sur des  blocs de 8*8 pour effectuer le traitement.

La DCT permet de passer de la représentation spatiale d’un signal à sa représentation spectrale.

La IDCT quand à elle permet de repasser du domaine spectral au domaine spatial.

Calcule de DCT et IDCT sur une matrice 8*8

Dans cette partie nous allons simplement réaliser la DCT et la IDCT sur un signal quelconque de 8*8 afin de constater les propriétés de bases  de ces opérations. Aucunes subtilités ou optimisations n’ont été ajoutés afin de ne pas rendre la compréhension plus difficile.

Pour commencer, on développe  les deux fonctions de base :DCT et IDCT, grâce aux formules théoriques, elles sont assez similaires et utilisent chacune deux tableaux. La DCT utilise un tableau représentant un signal et renvoie un tableau contenant les coefficients de la DCT.

La IDCT quand à elle prend en paramètre un tableau contenant les coefficients d’une DCT et renvoie un tableau représentant le signal reconstruit dans le domaine spatial.

DCT :

/* transformée DCT : on passe à cette fonction un bloc de 
8*8 pixel de l'image et elle renvoie la matrice des coeffs 
de la DCT coresspondante*/
void DCT_8(int pixel[8][8], float Coeff_DCT[8][8])
{
    int u=0, v=0;
    int x=0, y=0;
    float au=0, av=0;

    for(v=0;v<=7;v++)
    {
        for(u=0;u<=7;u++)
        {
            //Calcule des doubles sommes
            for(y=0;y<=7;y++)
            {
                for(x=0;x<=7;x++)
                {
                    Coeff_DCT[v][u]+=pixel[y][x]*(cos((PI*(2*x+1)*u)/16)*cos((PI*(2*y+1)*v)/16));
                }
            }

            //Calcule des facteurs d'ortogonalité 
            if(u==0){au=(1/sqrt(2));}
            else {au=1;}

            if(v==0){av=(1/sqrt(2));}
            else{ av=1;}

            //Calcule du coefficient complet 
            Coeff_DCT[v][u]=Coeff_DCT[v][u]*0.25*au*av;
        }
    }
}
Calcule de la DCT

IDCT :

/* transformée inverse de la DCT, on passe en parametres
une matrice de coefficients et elle renvoi une matrice 
de nombre entier representant la martice de départ */
void IDCT_8(float Coeff_DCT[8][8], int matrice_reconstruite[8][8])
{
    int u=0, v=0;
    int x=0, y=0;
    float au=0, av=0;
    //Matrice intermédiaire pour travailler en nombre réel
    float f[8][8]={0};

    for(y=0;y<=7;y++)
    {
        for(x=0;x<=7;x++)
        {
            for(v=0;v<=7;v++)
            {
                for(u=0;u<=7;u++)
                {
                    if(u==0){au=1/sqrt(2);}
                    else {au=1;}

                    if(v==0){av=1/sqrt(2);}
                    else{ av=1;}
                    f[y][x]+=Coeff_DCT[v][u]*au*av*cos(((2*x+1)*PI*u)/16)*cos(((2*y+1)*PI*v)/16);
                }
            }
            f[y][x]*=0.25;
            //Conversion réel entier avec arrondi 
            matrice_reconstruite[y][x]=floor(f[y][x]+0.5);
        }
    }
}
Calcule de la IDCT

On utilise maintenant ces deux fonctions pour calculer la DCT d’une matrice représentant un signal et ensuite la IDCT pour voir si il est possible de retrouver notre matrice de départ :

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#define N 8
#define PI 3.141592653589793

void DCT_8(int pixel[8][8], float Coeff_DCT[8][8]);
void IDCT_8(float C[8][8], int matrice_reconstruite[8][8]);

int main(int argc, char const *argv[])
{
	int i=0,j=0,k=0;

	float coeff_DCT[8][8]={0};//Matrice pour placer les coeff de la DCT
	int matrice_reconstruite[8][8]={0}; //Matrice pour placer le signal reconstruit 
	//Matrice representant le signal de base
	int matrice[8][8]={{244,243,118,154,126,246,137,184},
                   	   {178,127,196,155,184,184,147,245},
                       {114,116,134,231,145,166,214,112},
                       {178,127,196,155,184,184,247,245},
                       {200,224,133,145,105,167,237,118},
					   {137,263,118,154,126,246,137,89},
                   	   {178,127,196,255,184,184,147,245},
                       {114,116,134,231,145,166,247,198}};
	
    //Calcule de la DCT sur la matrice d'origine
    //On place les coeff dans coeff_DCT
    DCT_8(matrice, coeff_DCT);

    //Calcule de la IDCT grace à la martice des coeff
    //On place le signal regénérer dans martrice_reconstruite
    IDCT_8(coeff_DCT, matrice_reconstruite);
    

	//Affichage des differentes etapes     
    for(k=0;k<4;k++)
    {
    	if(k==0)puts("\nMatrice d'origine :");
    	if(k==1)puts("\nMatrice des coefficients :");
    	if(k==2)puts("\nMatrice reconstruite :");
    	if(k==3)puts("\nDifférence Origine/Reconstruite:");

    	for(i=0;i<8;i++)
    	{
    		for(j=0;j<8;j++)
    		{
    			if(k==0)printf("%d ",matrice[i][j]);
    			if(k==1)printf("%5.1f ",coeff_DCT[i][j]);
    			if(k==2)printf("%d ",matrice_reconstruite[i][j]);
    			if(k==3)printf("%d ",matrice[i][j]-matrice_reconstruite[i][j]);
    		}
    		printf("\n");
    	}    	
    }
    return 0;
}

 On obtient le résultat suivant :

Matrice d'origine :
244 243 118 154 126 246 137 184 
178 127 196 155 184 184 147 245 
114 116 134 231 145 166 214 112 
178 127 196 155 184 184 247 245 
200 224 133 145 105 167 237 118 
137 263 118 154 126 246 137 89 
178 127 196 255 184 184 147 245 
114 116 134 231 145 166 247 198 

Matrice des coefficients :
1385.2 -62.7  22.3  19.7 -20.8  50.7  -7.6 -82.0 
  5.5  29.0  47.8  38.4   4.2 -36.1  42.0  15.2 
 22.2 -15.4  -7.4 -21.1  69.1 -21.6  44.7 -43.9 
  6.5 129.7  61.6  83.7 -65.1 -101.9   9.4 -83.9 
 26.7 -14.0  86.5  27.1 -28.2  26.5 -36.9  15.5 
 53.4 -11.7 -12.6 -14.6  48.8  -2.8  39.7  -6.5 
-73.1  33.9 -42.3  67.1 -86.5   7.2 -79.1 -79.2 
-24.7  36.1 -11.0   3.8   6.7  61.6 -45.1 -24.4 

Matrice reconstruite :
244 243 118 154 126 246 137 184 
178 127 196 155 184 184 147 245 
114 116 134 231 145 166 214 112 
178 127 196 155 184 184 247 245 
200 224 133 145 105 167 237 118 
137 263 118 154 126 246 137 89 
178 127 196 255 184 184 147 245 
114 116 134 231 145 166 247 198 

Différence Origine/Reconstruite:
0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 
Affichage de la console

La DCT calcule une matrice de 64 coefficients représentant l’image dans le domaine spectral. Ensuite on  utilise cette matrice de coefficients pour calculer la  DCT Inverse (IDCT) et vérifier que le signal reconstruit est bien identique au signal de départ. Au final on constate que la matrice reconstruite à partir de la transformée est rigoureusement identique  à la matrice de base. Cet exemple montre la propriété sans pertes de la DCT : avec un nombre fini de coefficients et en n’oubliant pas les arrondis dans le code, il est possible de reconstruire exactement le signal de départ.

Réduction de l’information

Maintenant que nous pouvons réaliser la DCT et la DCT inverse nous allons montrer pour quelle raison la transformée en cosinus discret peut être utilisée pour réaliser de la compression de données.

Pour observer ses propriétés nous allons modifier les coefficients de la DCT et constater l’impact sur le signal reconstruit par la IDCT.

Pour cela nous allons utiliser une matrice dite « de quantification » qui permet de diviser la matrice des coefficients de la DCT par un facteur quelconque. Ensuite pour retrouver une matrice de coefficients proche de l’original il faut re-multiplier par la matrice de quantification et enfin appliquer une IDCT. Ces deux opérations semblent inutile à première vue, mais elles ont pour but de mettre à zéro les coefficients proches de zéro ou les coefficients inutiles.

Voici les deux fonctions de quantification et de dé-quantification :

/*Cette fonction réalise la quantification de la matrice des coefficients*/
/*L'indice permet de quantifier plus ou moins la matrice des coefficients*/
void Quantification(float Coeff_DCT[8][8],int Coeff_Quant[8][8],int indice_quantifiaction)
{
    int u=0, v=0;
   
   //On parcour la matrice des coefficients
    for(v=0;v<=7;v++)
    {
        for(u=0;u<=7;u++)
        {
           Coeff_Quant[v][u]=(int)trunc(Coeff_DCT[v][u]/(1+((1+u+v)*indice_quantifiaction))); 
           /*division par 1+((1+u+v)*indice_quantifiaction) et arrondi du coefficient*/
        }
    }
}
Quantification de la matrice des coefficients
/*Cette fonction réalise la dé-quantification de la matrice des coefficients*/
/*Afin de retrouver une matrice des coefficients proche de l'originale*/
void Dequantification(float Coeff_DCT[8][8],int Coeff_Quant[8][8],int indice_quantifiaction)
{
    int u=0, v=0;
   
    for(v=0;v<=7;v++)
    {
        for(u=0;u<=7;u++)
        {
           Coeff_DCT[v][u]=(int)trunc(Coeff_Quant[v][u]*(1+((1+u+v)*indice_quantifiaction))); 
           /*multiplication par 1+((1+u+v)*indice_quantifiaction) et arrondi du coefficient*/
        }
    }
}
Dé-quantification des coefficients
    DCT_8(matrice, coeff_DCT);
    Quantification(coeff_DCT,coeff_Quant,1);
    Dequantification(coeff_DCT,coeff_Quant,1);
    //Calcule de la IDCT grace à la martice des coeff
    //On place le signal regénérer dans martrice_reconstruite
    IDCT_8(coeff_DCT, matrice_reconstruite);

On obtient le résultat suivant sur une matrice obtenue à partir d’une image réelle :

Matrice d'origine :
162 162 162 161 162 157 163 161 
162 162 162 161 162 157 163 161 
162 162 162 161 162 157 163 161 
162 162 162 161 162 157 163 161 
162 162 162 161 162 157 163 161 
164 164 158 155 161 159 159 160 
160 160 163 158 160 162 159 156 
159 159 155 157 158 159 156 157 

Coefficients quantifiée:
641  1  0  0  0  0  0  0 
 2  0  0  0  0  0  0  0 
-1  0  0  0  0  0  0  0 
 0  0  0  0  0  0  0  0 
 0  0  0  0  0  0  0  0 
 0  0  0  0  0  0  0  0 
 0  0  0  0  0  0  0  0 
 0  0  0  0  0  0  0  0 

Matrice reconstruite :
161 161 161 161 161 160 160 160 
161 161 161 161 161 161 160 160 
162 162 161 161 161 161 161 161 
162 162 161 161 161 161 161 161 
161 161 161 161 161 160 160 160 
160 160 160 160 160 160 159 159 
160 160 159 159 159 159 159 159 
159 159 159 159 158 158 158 158 

Différence Origine/Reconstruite:
1 1 1 0 1 -3 3 1 
1 1 1 0 1 -4 3 1 
0 0 1 0 1 -4 2 0 
0 0 1 0 1 -4 2 0 
1 1 1 0 1 -3 3 1 
4 4 -2 -5 1 -1 0 1 
0 0 4 -1 1 3 0 -3 
0 0 -4 -2 0 1 -2 -1 

On remarque finalement que la matrice quantifiée ne contient plus que 4 coefficients non nuls, et pourtant après dé-quantification et IDCT inverse, l’erreur entre le signal d’origine et le signal reconstruit est plutôt faible. En résumé, nous sommes passés de 64 coefficients à seulement 4 pour décrire un signal proche de l’original, sur ce signal en particulier nous avons réduit la taille d’information par 16. Autrement dit, si une personne à l’autre bout du réseau, par exemple, connaît la méthode de dé-quantification et de transformée inverse que j’ai utilisé, alors il est en mesure de reconstruire quasiment le signal d’origine si je lui fournis seulement 4 coefficients, au lieu de lui envoyer les 64 pixels de l’image de base.

Voilà finalement tout l’intérêt de la DCT, car on constate que si l’on réduit intelligemment le nombre des coefficients il est quand même possible de retrouver une variante exploitable de l’information d’origine. Ce qui serait tout bonnement impossible avec une transformée de Fourier, du fait du phénomène de Gibbs entre autres.

Dans un prochain article, nous aborderons la compression sans pertes des matrices de coefficients afin de réduire encore plus le volume des données représentant une image.

Installation d’OpenCV & CUDA sur Ubuntu 14.04

opencv-logo2

Cette article va vous présenter une méthode pour installer OpenCV ainsi que le support de CUDA dans un environnent Ubuntu 14.04.

La première chose à faire, si vous ne l’avez pas encore fait, est d’installer CUDA sur votre machine : Installation de CUDA 6.5 sur Ubuntu 14.04

Note : n’essayez pas d’installer OpenCV avant d’avoir installer correctement CUDA, sinon OpenCV ne pourra pas compiler les bibliothèques comme GPU nécessitant le module CUDA.

  • Téléchargement

Dans un premier temps, télécharger OpenCV : Site officiel OpenCV

Décompiler l’archive et déplacer le dossier « opencv-2.4.10 » dans votre répertoire home.

  • Génération des Makefile

Une fois le dossier déplacé, lancer la console (ctrl + alt + t) et exécuter les instructions suivantes :

La commande cmake permet de générer le Makefile pour la compilation d’OpenCV. Les options de cmake pour OpenCV sont nombreuses, par exemple dans notre cas les options permettent de prendre en charge CUDA (WITH_CUDA=ON -D) ou encore le support de QT pour les interfaces graphique (WITH_QT=ON), si vous n’avez pas besoin du support de python vous pouvez supprimer les paramètres relatif à Python.

Pour connaître toutes les options possibles pour compiler OpenCV, je vous invite à ouvrir le fichier CMakeLists.txt disponible à la racine du dossier « opencv-2.4.10 ». A l’intérieur, vous trouverez toutes les indications pour ajouter et supprimer des parties d’OpenCV selon vos besoins.

Note : si votre machine utilise un processeur Intel, je vous invite à installer les IPP d’Intel avant de générer le Makefile. Les IPP permettent d’accélérer l’exécution des fonctions OpenCV sur les machines équipées d’un processeur Intel.

$ cd ~
$ cd opencv-2.4.10
$ mkdir build
$ cd build
$ cmake -D WITH_CUDA=ON -D WITH_TBB=ON -D BUILD_NEW_PYTHON_SUPPORT=ON -D WITH_V4L=ON -D INSTALL_C_EXAMPLES=ON -D INSTALL_PYTHON_EXAMPLES=ON -D BUILD_EXAMPLES=ON -D WITH_QT=ON -D WITH_OPENGL=ON -D WITH_VTK=ON ..

Une fois la génération du Makefile terminée, vérifier attentivement chaque option et notamment  celle concernant CUDA (use cuda = YES ) et Nvidia.

Si tout est bon alors il est maintenant possible de passer à la compilation.

  • Compilation

Il faut maintenant compiler OpenCV, cette étape prend pas mal de temps (environ 3heures pour moi) .

Remplacer N dans la commande suivante par le nombre de threads à affecter à la compilation, si vous ne savez pas combien mettre, remplacer simplement N par 1, la compilation durera juste un peu plus longtemps.

$ sudo make -j N

Une fois la compilation terminée il faut installer OpenCV :

$ sudo make install

Voilà, si vous n’avez pas de messages d’erreur OpenCV est maintenant installé sur votre machine. 🙂

  • Vérification

Afin de vérifier le bon fonctionnement de l’installation ainsi que la prise en charge de CUDA, nous allons maintenant mettre en œuvre un exemple fourni avec OpenCV  :

$ cd ~
$ cd opencv-2.4.10
$ cd samples
$ cd gpu

Une fois dans le dossier gpu, modifier le fichier CMakeLists.txt (faites une sauvegarde du fichier original si vous le souhaitez).

Remplacer le contenue du fichier par celui-ci :

Cmake_minimum_required(VERSION 2.8)
project(HogCode)
find_package(OpenCV REQUIRED)
add_executable(HogCode hog.cpp)
target_link_libraries(HogCode ${OpenCV_LIBS})

ensuite, compiler et exécuter HogCode :

$ cmake .
$ make
$ ./HogCode road.png --camera 0

Vous devez voir apparaître une fenêtre affichant votre webcam, la touche m permet de switcher entre l’exécution de l’algorithme sur le CPU et sur le GPU. Si tout est installé correctement sur votre machine, vous pouvez constater la différence entre la vitesse d’exécution de l’algorithme  sur le CPU et sur le GPU.

  • Conclusion

Ce tutoriel est maintenant terminé, vous pouvez maintenant commencer à utiliser CUDA pour augmenter les performances de vos algorithmes de traitement d’images avec OpenCV.

Installation de CUDA 6.5 sur Ubuntu 14.04

nvidia_logo

Cet article présente une méthode d’installation du toolkit 6.5 de CUDA dans un environnement Ubuntu (64 bits) version 14.04.

Cette installation a été testée avec une carte graphique Nvidia GTX860M (architecture Maxwell).

Avant de commencer l’installation, vérifier bien que votre configuration matériel est compatible CUDA: pour cela vérifier que votre carte graphique se trouve dans la liste communiquée par Nvidia : GPU supportant CUDA

  • Ajout du dépôt CUDA

Dans un premier temps il faut récupérer le fichier .deb sur la page de téléchargement Nvidia  : Téléchargement .deb CUDA

deb

Une fois le téléchargement terminé, ouvrir la console (ctrl + alt + t) et rendez-vous dans le dossier où a été téléchargé le fichier .deb, ensuite exécuter les deux commandes suivantes :

$ sudo dpkg -i cuda-repo-ubuntu1404_6.5-14_amd64.deb 
$ sudo apt-get update 

Ces commandes permettent d’ajouter le dépôt CUDA à la liste des dépôts du gestionnaire de paquets (apt-get) et de les mettre à jour

  • Installation de CUDA

Maintenant nous allons procéder à l’installation du sdk et du toolkit CUDA à proprement parler. Rendez-vous dans la console et entrer la commande suivante :

$ sudo apt-get install cuda 

Suivez le guide qui s’affiche dans la console et attendez la fin du téléchargement (1Go Environ).

Une fois l’installation terminée,exécuter un redémarrage du système :

$ sudo reboot

Avant de continuer, vérifier bien que le pilote de votre carte graphique à été mis à jour, pour cela rendez vous dans « Logiciels & mises à jour », ouvrez l’onglet : « Pilotes additionnels » et vérifier que le pilote de votre carte graphique est bien de type « Nvidia propriétaire » :

log&maj
Si tout est OK l’installation semble s’être bien passée…

  • Ajout des variables d’environnement CUDA

Pour ajouter les variables d’environnement, il faut modifier le fichier .bashrc qui se trouve dans votre répertoire home :

$ cd ~
$ ls -a
$ sudo gedit .bashrc

Et ajouter à la fin du fichier les lignes suivantes :

#Cuda

export CUDA_HOME=/usr/local/cuda-6.5 
export LD_LIBRARY_PATH=${CUDA_HOME}/lib64 
 
PATH=${CUDA_HOME}/bin:${PATH} 
export PATH 

Sauvegarder et fermer gedit.

  • Installation des exemples

Nvidia fournit tout un ensemble d’exemples souvent codé en c/c++ qui illustre les possibilités et les fonctionnalités de CUDA. Nous allons installer ces exemples pour vérifier que toute l’installation s’est dérouler correctement :

Ouvrir la console et exécuter les 3 instructions suivantes :

$ cuda-install-samples-6.5.sh  ~ 
$ cd ~/NVIDIA_CUDA-6.5_Samples 
$ make 

La compilation des exemples prend un certain temps (20 minutes environ).

Une fois les exemples compilés, il faut se rendre dans le dossier où ils ont été copié :

cd /NVIDIA_CUDA-6.5_Samples/bin/x86_64/linux/release

Une fois dans le dossier, exécuter l’exemple deviceQuery qui indique les carte graphiques compatibles CUDA disponibles sur le système.

$ ./deviceQuery

Vous devriez alors obtenir une console ressemblant à celle-ci :

deviceQuery

Si c’est le cas alors CUDA est installé correctement sur votre machine !

  • Démonstration CUDA

Pour terminer ce tutoriel, je vous propose de lancer un seconde exemple beaucoup plus parlant que le deviceQuery pour illustré les possibilités de CUDA :

$ cd ~
$ cd /NVIDIA_CUDA-6.5_Samples/2_Graphics/Mandelbrot
$ ./Mandelbrot

N’hésitez pas à jouer avec les options pour constatez les différences entre l’exécution de l’algorithme sur GPU et CPU par exemple.

Mandelbrot

Voila, si tout fonctionne correctement, alors vous avez les outils nécessaires pour développer des programmes utilisant le calcul sur GPU 🙂

Asservisement en position Robot KSR10

Aujourd’hui je vous présente une nouvelle carte destinée à améliorer un peu le robot KSR10 que je vous ai présenté dans un article précédent.  Comme je l’ai dit, le robot KSR10 ne dispose pas, à l’origine, de capteur de position ni de moyen de réaliser des mouvement précis, j’ai donc décidé de lui ajouter quelques capteurs de position et de réaliser une carte d’asservissement afin de contrôler précisément ses mouvements.

I-Ajout des capteurs de position

Pour connaître la position des axes, j’ai utilisé des simples potentiomètres, car ils ont l’avantage d’être bon marché, plutôt faciles à installer et en plus ils fournissent une information absolue sur la position. Le seul inconvénient est qu’ils risquent de s’user avec le temps, mais comme je ne prévois pas d’utiliser le robot de façon intensive, je pense qu’ils feront parfaitement l’affaire 🙂

Capteur2Capteur1

II-Conception de la carte d’asservissement

La carte d’asservissement doit permettre au robot de pouvoir positionner ses axes en fonction d’une consigne donnée par l’utilisateur, indépendamment des conditions extérieures du système (Ex : charge au bout du bras), ceci afin de pouvoir répéter des séquences de mouvement précis plusieurs fois d’affilée.

Pour réaliser la carte, j’ai décidé de n’utiliser que des composants analogiques, comprendre par là : AOP. L’asservissement recherché est un PID basique.

Le principe est simple : on récupère la position réelle du bras grâce au potentiomètre, on compare avec la position souhaitée par l’utilisateur, et enfin on génère la commande du moteur en fonction de l’erreur entre la consigne et la position. Ici, la commande à générer est une simple PWM qui sera appliqué sur l’entrée « sens » de l’interface de puissance. Pour expliquer simplement, un état logique 0 sur l’entrée sens provoque le déplacement de l’axe dans un sens, et un 1 logique sur sens provoque le déplacement dans le sens opposé. Donc lorsque la position du bras est très éloignée de la consigne, la commande du moteur doit être à fond dans un sens (PWM a 100% ou PWM à 0%) mais lorsque le position se rapproche de la consigne, le bras doit freiner un peu et venir s’arrêter juste à la consigne (PWM à 50% le bras maintient sa position).

La carte peut se diviser en trois parties :

1) L’adaptation des signaux d’entrée : c’est-à-dire la mise en forme du signal du capteur pour garder une grande plage de variation du signal, l’acquisition de la consigne et enfin le calcul de la différence entre la position réelle et la consigne.

Le schéma suivant présente l’implémentation de cette première partie :

Partie 1

-Le capteur est connecté sur le connecteur J2, RV1 et RV2 permettent de régler la dynamique du capteur.

-U1:C et le filtre passe bas sert à l’acquisition de la consigne.

-U2:A est un montage soustracteur qui permet de réaliser la différence entre la consigne et la position réelle.

2) La deuxième partie se compose de toute la partie PID, on utilise le montage de basse du PID à AOP, c’est-à-dire un amplificateur inverseur, un dérivateur et un montage intégrateur et on injecte le tout dans un additionneur afin d’obtenir le coefficient pour la génération de la PWM.

Partie 2

3) Et enfin la dernière partie : l’élaboration de la commande, cette partie revient simplement à générer une PWM dont le rapport cyclique est proportionnel au coefficient en sortie du PID.

III-Test de la solution

Je met ici deux petites vidéos d’un test que j’ai réalisé pour valider la solution technique choisie. L’asservissement n’est pas optimisé au niveau de la rapidité mais on peut déjà voir sont effet 😉

IV-Réalisation

La carte terminée :

Carte asservisement position

La carte terminée permet d’asservir un seul axe du robot, il faut donc 5 cartes pour asservir le robot  complètement.

V- Implémentation

Pour l’instant, l’implémentation n’est pas terminée car les 5 cartes sont assez longues à réaliser, et coûtent relativement cher à produire (environ 20 euros par carte) donc j’attends un peu avant d’équiper tous les axes du robot.

Interface de puissance entre Arduino et KSR10

Bonjour, aujourd’hui je vous présente l’interface de puissance que j’ai réaliser pour commander un robot KSR10 avec une arduino.

Tout d’abord le robot KSR10 est un petit bras manipulateur 5 Axes vendu en kit par fabriquant Velleman que l’on trouve aux alentours de 40euro dans les bons magasins. Sont seul défaut est a mon avis la commande, en effet il n’est à l’origine pilotable que par une manette à contacts sec, ce qui l’empêche d’être utiliser autrement qu’en jouet. C’est pourquoi j’ai décider de réaliser une carte qui permettra de remplacer la manette d’origine et de piloter le robot avec un microcontrôleur.

Robot KS10 de VellemanI- Conception de la carte

Le but de la carte est tout simplement de remplacer la manette du robot, sans toucher au câblage d’origine du robot, ce qui présente quelques petits inconvénients, notamment l’impossibilité d’utilisé un pont en H traditionnel.

Voici le schéma du module de basse pour la commande d’un seul moteur :

Module de basse

 

On peut décomposer en deux partie ce module, la première partie ce compose d’un 4001 qui à pour but d’empêché l’activation en même temps des deux sens de rotation du moteur afin d’éviter de détériorer la carte  suite à des erreurs de programmation par exemple. La seconde partie c’est la partie puissance avec les 4 transistors qui permettent de commander les moteurs dans les deux sens, et avec une vitesse variables en appliquant un signale PWM sur l’entrée mise-en-marche (mem1) de la carte.

Il est à noter que la carte complète est composer d’un module pour chaque moteurs soit un totale de 5 pour piloter l’ensemble du robot.

Voici ce que cela donne une fois terminer :

carte terminer

II- Réalisation

Après la conception, on passe à la réalisation :

Crte graver

Et voici le résultat final, avec la carte arduino et le robot  :

Carte terminer

Note : Le port DB9 sur la droite permet de brancher un joystick analogique pour piloter le robot

III- Démonstration

Si vous souhaitez avoir un aperçu du fonctionnement je vous invite à regarder la vidéo de démonstration :

Pour terminer je dirai que la carte fonctionne correctement mais que la programmation et le pilotage par le microcontrôleur n’est pas simple du tout car le robot ne dispose à l’origine d’aucun capteur de position des axes, donc la commande s’effectue simplement en activant les moteur pendant un temps plus ou moins grands en fonction du mouvement souhaiter, ce qui rends compliquer, voir impossible l’utilisation en autonomie du robot .

Si vous avez apprécier ce post je vous invite à aller lire mon deuxième article sur le robot KSR10, il présente une méthode pour asservir en positon le robot et améliorer ça capacité a répéter des mouvements précis de manière autonome.

Lien : http://robin-narbey.fr/asservisement-en-position-robot-ksr10/

InnoRobo 2013 : Présentation

InnoRobo se déroule cette année du 19 au 21 mars au centre des congrès de Lyon.InnoRobo-Header

Pour ceux qui ne connaissent pas, InnoRobo est un salon dédié à la robotique de services, bien que la première édition date de 2011 c’est devenu en 2 ans un rendez-vous incontournable en la matière. On retrouve sur le salon des grands noms du domaine comme : Aldebaran-Robotics qui fabrique les fameux robots NAO ou IRobot et ces Roomba, mais pas seulement, on retrouve aussi beaucoup de laboratoires de recherches, des startups ou encore des écoles spécialiser dans la robotique comme l’IMERIR de Perpignan ou encore l’ENSEIB de Bordeaux.

Pour résumer, InnoRobot c’est : 120 exposants, 34 pays différents représenter, 15 000 visiteurs attendu …

InnoRobo propose au cour des 3 jours plusieurs conférences avec des experts mondialement reconnus dans des domaines touchant de très près la robotique de service  :

  • Bruno Bonnell : Cérémonie d’ouverture.
  • Hugh Herr (MIT) : La robotique médical et de santé.
  • Dmitry Grishin  : Investir en robotique.
  • Dominique Sciamma : L’influence du design.
  • Manuela Veloso : La symbiotique humaine et interaction des robots.
  • Aviad Maizels / Détection 3D et vision robot.

Cette année comme il y a deux ans je me rendrai a InnoRobo et je vous conseil vivement si vous le pouvez d’aller y faire un petit tour, c’est une très bonne occasion de pouvoir discuter robotique, informatique, nouvelles technologies avec des vrais passionner.

Voilà cette petite description succincte de l’événement est terminer, mais si vous souhaitez des informations complémentaires je vous encourage à vous rendre sur le site du salon : http://www.innorobo.com  

Ouverture de mon site perso

Bonjour à tous et bienvenue sur mon site personnel !

Je m’efforcerai de poster ici régulièrement mes réflexions sur des sujets scientifiques bien souvent relatifs à l’électronique, l’informatique, la programmation, ou encore la robotique afin d’en faire profiter le plus grand nombre.

N’hésitez pas à interagir en postant des commentaires, je me ferais une joie de vous répondre.

A bientôt et bonne lecture !