Tir automatisé avec catapulte

Participant

  • KERNACKER Thomas(GMP)
  • ASTRIC François-David (GMP)
  • KUPFER Paulin (GEII)

Le Lanceur (GMP)

Le projet du lanceur consiste à lancer une balle de squash de 24g dans une cible (panier) à une distance de 10m.

La contrainte que nous possédions était de faire tenir notre système complet dans un cube de 25 cm³.

 

Définition du besoin

Le diagramme « Bête à corne » nous permet de définir la fonction principale du lanceur.

 

Le diagramme « Pieuvre » permet de définir les fonctions principales et les fonctions contraintes de notre système.

 

 

Schéma Cinématique

La Conception

Au niveau de la conception du lanceur, nous avons décidés de nous rapprocher de l’idée du canon.

Le corps principale du lanceur est un fût où l’on vient placer les divers éléments du système d’armement et de propulsion.

Lanceur 3D

Au départ, nous avions envisagés trois solutions différentes pour armer notre lanceur.

La solution de gauche consiste à compresser un ressort de compression pour propulser la balle. L’inconvénient de cette solution est qu’elle n’est pas très modulable car l’on ne peut placer qu’un seul ressort.

La solution du centre consiste à tendre des élastiques pour envoyer la balle. Cette solution est pratique car l’on peut ajouter ou retirer facilement les couches d’élastiques pour régler la puissance de tir.

La dernière solution consiste à tendre des ressorts de tractions. Nous avons choisis cette solution car elle est assez modulable, on peut placer jusqu’à 4 ressorts sur le système, mais aussi pour le fait de travailler avec de « vrais » composants mécaniques.

Le lancé

Tout d’abord il nous a fallu déterminer les conditions avec lesquelles nous enverrons notre balle de squash à 10m. Nous supposons au départ plusieurs variables :

  • Durée de vol de la balle de squash = 0.5s pour un tir très rapide
  • Angle de tir = 15° pour un tir tendu

Grâce aux équations du mouvement, nous trouvons une vitesse de balle égale à 14m/s.

Pour évaluer l’énergie nécessaire au tir d’une balle de squash de 24g, nous avons alors réalisé un tableau Excel, nous donnant une énergie d’environ 2.3 Joule.

 

Cette valeur est très satisfaisante car situé après la chute de la courbe de l’énergie.

 

Dimensionnement

Avec la vitesse de 14m/s, nous déterminons ensuite les ressorts et moteurs nécessaires à la charge du tir.

Nous trouvons alors une raideur de ressort d’environ 4N/mm. Selon notre conception, celle-ci sera acquise grâce à 4 ressorts d’1N/mm chacun ou 8 ressorts de 0.5N/mm.

De même, nous déterminons un couple de sortie nécessaire à l’armement de 0.81N.m.

Nos recherches sur différents moteurs déjà disponible au sein de l’IUT nous ont permis de récupérer un petit moteur avec un couple de 3kg.cm, ce qui équivaut à 0.29N.m.

Son couple n’étant pas suffisant, il nécessitera l’accompagnement d’un système de réduction.

Par la suite nous avons déterminés le nombre de dents des deux roues dentées afin d’obtenir un couple de 0.28N.m.

Pour le système de réduction; on considérera un rendement hypothétique de 0.85.

Le système d’armement

Afin d’armer notre lanceur, nous avons conçus un système d’armement reprenant le principe d’un treuil.

Système d’armement 3D

Pour ce faire, on entraîne un axe avec un moteur accompagné d’un système de réduction. Cet axe va enrouler un câble en acier qui va ensuite tendre notre système de propulsion.

Nous avons dimensionnés nos engrenages de tel sorte à pouvoir récupérer un moteur fourni par l’IUT, ce qui nous évite des frais supplémentaires pour notre projet.

La pièce la plus complexe de système est l’axe car il doit avoir une tolérance géométrique élevé sur toute sa longueur (∅4 g6) pour permettre un ajustement juste glissant dans le cylindre tendeur.

Plan axe 2D

Cylindre tendeur 3D

L’axe est situé en dessous de la section droite du tube car il faut permettre au câble en acier de s’enrouler autour du cylindre tendeur de façon à garder le système de propulsion coaxial avec le fût.

L’arrêt axial de l’axe s’effectue par deux anneaux élastiques car il ne subit pas d’effort axial particulier. Il est guidé par deux coussinets en bronze afin de minimiser les frottements et d’avoir un rendement le plus élevé possible.

Coussinet en bronze

L’ensemble des pièces sont en aluminium dû à la légèreté de cette matière sauf l’axe qui est quant à lui en acier, afin de ne pas se faire cisailler par le câble en acier.

 

Le système de propulsion

Afin de propulser la balle de squash, nous avons conçu un tige guidée en translation à travers le fût du lanceur par une douille en plastique Igus.

Nous avons choisis cette douille en plastique car sa technologie lui permet d’avoir un coefficient de frottement très faible, qui se rapproche de la qualité d’une cage à bille, à moindre coût.

Système d’armement 3D

Douille plastique Igus 3D

L’ensemble de la tige est composé de 4 pièces afin de pouvoir la monter dans notre système de propulsion.

Ces quatre pièces sont mises en positions par guidages cylindriques et sont ensuite vissées sur l’axe de la tige.

Vue éclatée de la tige 3D

Le système de propulsion comportera donc 2 paires de ressorts différents suite à la rupture de stock de nos fournisseurs.

Ces ressorts sont fixés sur le disque et la tige afin de propulser l’ensemble de la tige, guidée par la douille en plastique.

Le disque est fixé dans le fût par deux vis M4 et est ensuite goupiller pour lui permettre de bien rester fixe suite aux efforts qu’il va subir.

La pièce tenant la câble en acier a été conçu afin de permettre au câble de bien rester dans le plan de la section droite du fût.

Pièce porte-câble 3D

L’ensemble des pièce sont en aluminium pour minimiser le poids du système.

 

Fixation au bâti

L’ensemble du fût est tenu par une pièce intermédiaire permettant de la tenir est de régler son angle de tir. Malheureusement, faute de temps, nous n’avons pas pu réaliser ce système.

Fixation tube 3D

Le Système de Visée (GEII)

Le système de visée sera par reconnaissance visuel d’une couleur autour de la cible . Il fonctionnera sur le principe d’un tracking de couleur rouge et d’une gestion de 2 servos-moteur.

Le Matériel

  • 2 Servo-moteur. J’ai utilisé des moteur 50 Hz, la Fréquence est importante à connaitre car il faut la renseigner dans certains programmes, en effet un servo moteur fonctionne avec pour consigne une impulsion de 1 à 2 ms sur sa fréquence de fonctionnement. Pour la bibliothèque servo.h la fréquence est calculée toute seul.
  • Un Raspberry pi au minimum 2 (je n’ai pas testé sur une version antérieur).Il est nécessaire d’avoir une certaine puissance de calcul pour faire du traitement d’image.
  • Une camera Pi module V1 suffi car à 10 metre une cible de 1m mesure 11 pixel de rayon soit une tache de 380 pixel. Le calcul vaut : rayon=2549*1/tan(26.75) *10 . L’aire = rayon * rayon * pi.

Le système

Il n’est pas très compliqué. La Caméra pi a son emplacement dans la carte. Les servo-moteurs peuvent avoir leur alimentation extérieur mais on peut aussi les câbler sur le 5 V de la Raspberry. Il faut aussi réunir toutes les masses. Les codes couleurs des câbles des servo moteur sont precis: brun = la terre, rouge = le +, jaune = la consigne.

Le Programme

Le programme est donc un tracking du rouge(h = 20, s = 240, v = 200) on aurait aussi pu le faire avec d’autre couleur mais il faut en avoir une qui ne soit pas confondable avec l’élément du décor.Le programme complet sera en fin de ce paragraphe, il incluras tout les outils facilitant le paramétrages du système.

Le programme consiste en trois parti:

  1. Le traitement de l’image
  2. Positionnement des coordonné
  3. Mise en mouvement des moteurs

 

Le traitement de l’image est une binarisation des pixels rouges en blanc. Pour cela il faut d’abord passer l’image de BGR (bleu, vert, rouge) en HSV (teinte, saturation, brillance). Ensuite le programme crée un masque de recherche qui passe sur chaque pixel pour le comparé.

En second, le programme va récupérer les coordonnés de la plus grande tache, cette tache sera notre cible, il faudra parfois ajuster les valeur de s et h en fonction du décor car la luminosité peut faire varier ces valeurs. Cette partie calcul le centre de gravité de la tache et il déplace petit à petit les anciennes coordonnées. Lorsque ceci est fait, il dessine le cercle nous permettant de voir quelle tache il a désigné comme étant la plus grosse de notre image.

Enfin on va calculer l’angle à ajouter au lanceur pour qu’il puisse se replacer en face de la cible. Pour ce calcul il faut ajouter à l’ancien angle, le nouvelle angle qui vaut le rapport difference de pixel par rapport au centre sur les pixel max fois l’angle.

Avec la bibliothèque Servo on a seulement besoin de renseigner l’angle. Certain comme GPIO sur Raspberry demande des calculs supplémentaires dépendant de vos moteur mais ce sera toujours sur la base de a+(angle/180)*b.

Voici le programme:

#include « opencv/highgui.h »

#include « opencv/cv.h »

 

#include <iostream>

#include <stdlib.h>

#include <stdio.h>

#include <servo.h>

 

//methode mathematique

#define max(a, b) ((a) > (b) ? (a) : (b))

#define min(a, b) ((a) < (b) ? (a) : (b))

#define abs(x) ((x) > 0 ? (x) : -(x))

#define sign(x) ((x) > 0 ? 1 : -1)

 

// pas de l’object

#define STEP_MIN 5

#define STEP_MAX 100

 

IplImage *image;

 

// position de reference

CvPoint objectPos = cvPoint(-1, -1);

// parametre de couleur

int h = 20, s = 240, v = 200, tolerance = 15;

 

/*

* binarisation de l’image

*/

CvPoint binarisation(IplImage* image, int *nbPixels) {

 

int x, y;

CvScalar pixel;

IplImage *hsv, *mask;

IplConvKernel *kernel;

int sommeX = 0, sommeY = 0;

*nbPixels = 0;

Pif paf pouf

 

// creation du masque de binarisation

mask = cvCreateImage(cvGetSize(image), image->depth, 1);

 

// recreer l’image en couleur HSV

hsv = cvCloneImage(image);

cvCvtColor(image, hsv, CV_BGR2HSV);

 

// creation du masque de recherché de couleur

cvInRangeS(hsv, cvScalar(h – tolerance -1, s – tolerance, 0), cvScalar(h + tolerance -1, s + tolerance, 255), mask);

 

// definition de l’outil de reconnaissance

kernel = cvCreateStructuringElementEx(5, 5, 2, 2, CV_SHAPE_ELLIPSE);

 

// filtrage des parasite

cvDilate(mask, mask, kernel, 1);

cvErode(mask, mask, kernel, 1);

 

// On cherche le centre de l’objet

for(x = 0; x < mask->width; x++) {

for(y = 0; y < mask->height; y++) {

 

// Si le pixel est un de ceux tracké le prendre en compte pour le centre de gravité.

if(((uchar *)(mask->imageData + y*mask->widthStep))[x] == 255) {

sommeX += x;

sommeY += y;

(*nbPixels)++;

}

}

}

 

// affichage sur écran pour les tests

cvShowImage(« GeckoGeek Mask », mask);

 

 

cvReleaseStructuringElement(&kernel);

 

cvReleaseImage(&mask);

 

cvReleaseImage(&hsv);

 

// Si l’on a rien on considère l’objet au centre

if(*nbPixels > 0)

return cvPoint((int)(sommeX / (*nbPixels)), (int)(sommeY / (*nbPixels)));

else

return cvPoint(-1, -1);

}

 

/*

* ajout d’un cercle indicatif renseignant la position de l’objet

*/

Point addObjectToVideo(IplImage* image, CvPoint objectNextPos, int nbPixels) {

 

int objectNextStepX, objectNextStepY;

 

// Calcul de la position du cercle

if (nbPixels > 10) {

 

// Si aucune position trouvé

if (objectPos.x == -1 || objectPos.y == -1) {

objectPos.x = objectNextPos.x;

objectPos.y = objectNextPos.y;

}

 

// Deplacement du cercle vers l’object

if (abs(objectPos.x – objectNextPos.x) > STEP_MIN) {

objectNextStepX = max(STEP_MIN, min(STEP_MAX, abs(objectPos.x – objectNextPos.x) / 2));

objectPos.x += (-1) * sign(objectPos.x – objectNextPos.x) * objectNextStepX;

}

if (abs(objectPos.y – objectNextPos.y) > STEP_MIN) {

objectNextStepY = max(STEP_MIN, min(STEP_MAX, abs(objectPos.y – objectNextPos.y) / 2));

objectPos.y += (-1) * sign(objectPos.y – objectNextPos.y) * objectNextStepY;

}

 

 

} else {

 

objectPos.x = -1;

objectPos.y = -1;

 

}

 

// On dessine le cercle

if (nbPixels > 10)

cvDrawCircle(image, objectPos, 15, CV_RGB(255, 0, 0), -1);

 

cvShowImage(« GeckoGeek Color Tracking », image);

//retour des coordonee du point

Return objectPos;

}

 

 

int main() {

Servo moty;

Servo motX;

Point viseur;

Float x;

Float y;

 

Moty.attach(8);

Moty.attach(7);

while(1)

// Image & hsvImage

IplImage *hsv;

// Video Capture

CvCapture *capture;

 

int nbPixels;

 

CvPoint objectNextPos;

 

// initialization de la capture video

capture = cvCreateCameraCapture(200);

 

 

if (!capture) {

printf(« Video non prise.\n »);

return -1;

}

 

// creation de la fenetre

cvNamedWindow(« test « , CV_WINDOW_AUTOSIZE);

cvNamedWindow(« test Mask », CV_WINDOW_AUTOSIZE);

cvMoveWindow(« test Color Tracking », 0, 100);

cvMoveWindow(« test Mask », 650, 100);

 

// On prend l’image courrante

image = cvQueryFrame(capture);

 

 

objectNextPos = binarisation(image, &nbPixels);

viseur = addObjectToVideo(image, objectNextPos, nbPixels);

 

//mise en mouvement des moteurs

 

x=viseur.x/2549*26.75+x; //angle que l’on veut rajouter(2549 la resolution/26.75 l’angle de vue)

y=viseur.y/1944*20.7+y;

moty.write(y) ;

motx.write(x) ;

delay(15) ;

 

// Destruction de la fenetre

cvDestroyWindow(« test Color Tracking »);

cvDestroyWindow(« test Mask »);

cvReleaseCapture(&capture);

 

return 0;

 

}

Avancement

Le projet n’a pu être fini fautes de temps, ma principal difficulté ne fut pas dans le programme car chaque partie était assez simple mais dans l’installation de l’opencv sur Raspberry. Je n’ai jamais réussi à l’installer puis l’utiliser sur 2 raspberry différent. J’ai aussi pris du retard car après une mauvaise manipulation j’ai grillé une Raspberry du au nombreux changement durant mes test des moteurs en Arduino