Aller au contenu


Photo
- - - - -

Base pour simulateur simple pour la coupe de france de Robotique sous processing

CFR Eurobot

2 réponses à ce sujet

#1 Mike118

Mike118

    Staff Robot Maker

  • Administrateur
  • PipPipPipPipPip
  • 9 934 messages
  • Gender:Male
  • Location:Anglet
  • Interests:Robotique, Entrepreneuriat, Innovation, Programmation, Résolution de problème, Recherche de solutions, Mécanique, Electronique, Créer, Concevoir

Posté 06 avril 2022 - 05:43

Bonjour à tous, je vous partage ce qui pourrait être une base pour un simulateur pour la coupe de france de robotique qui tourne sous processing : https://processing.org/

Voici à quoi ça ressemble : 
app.JPG

 

 

Pour le moment c'est quelque chose de très basique ça prend une image png de la table correctement dimensionnée en pixel ( et que je joint aussi : 
tablegrille.png

Et ça permet de déplacer un robot ( actuellement représenté par un carré jaune ) avec les touches du clavier ( z q s d pour la translation du robot et a e pour la rotation ... ) et ça affiche des données comme la position du robot, son orientation etc ...  Cela peut être pratique pour "planifier" les différents trajets que doit faire votre robot pendant un match ..  mais ça peut assez facilement être modifié pour : 

  • d'autres type de table / carte, ( il suffit de changer l'image / les dimensions )
  • être connecté à une arduino par un port série pour afficher des données en temps réel, 
  • être mis en 3D au lieu d'être uniquement 2D .
  • mettre plus de robot ...

 

Ci joint le code : 

 

// Code réalisé par Mike118 de www. robot-maker.com.
// Ce Sketch peut servir de base pour un simulateur de robot pour la coupe de france de robotique
// la table est orientée de sorte à ce que l'axe de x soit la longeur de la table ( 3000mm )
// l'axe des y est la largeur de la table (2000mm) et l'origine au milieu bas. 
// x € [ -1500, 1500] et y € [0, 2000]
// Utilisez les touches du clavier a z e q s d pour déplacer le robot.

// Dimensions de la table en mm
int tablex = 3000;
int tabley = 2000;

// Coordonnées du robot en mm
int x=-1400;
int y=1200;
float z=0;

// vitesse du robot modifiées par le clavier
int vx=0;
int vy=0;
float vz = 0;

PImage table;

int framerate = 25;
int vmax = 500; // mm/s
float vzmax = PI/64;  // en Rad/s
   
void setup() {
  size(1200, 700); 
  frameRate(framerate);
  table = loadImage("tablegrille.png"); // 750 * 500 pixel  1 pixel = 4mm 
}


void draw() { 
  background(0);
  println(frameCount + ": " +  key);
  imageMode(CENTER);
  image(table,width/2,height/2);
  drawData() ;
  int l = 180;  // Largeur du robot
  int L= 180;   // Longuer du robot
  int margin =int(max(L/2,l/2)*sqrt(2));  // marge par rapport au bord
  
  x = constrain(x + vx, -tablex/2 + margin, tablex/2 - margin);
  y = constrain(y + vy, 0 + margin, tabley - margin);
  z += vz;
  if( z > 2 * PI) {
    z-= 2*PI;
  } else if (z < 0) {
    z+= 2*PI;
  }
  drawRobot(x, y, z, 255, 255, 0, 180, 180); 

} 


// Fonctions de conversions de position en mm en postion en pixels

int xToPixel(int x) {
  return x/4 + width/2 ;  // /4 car 1 pixel = 4mm
}

int yToPixel(int y) {
  return -y/4 + height -100; //  /4 car 1 pixel = 4mm et -100 pour la bordure de noir
}

// drawRobot(int x, int y, float z, int r, int g, int b, int l, int L)
// x y position en mm
// z angle en radian
// r g b, entier entre 0 et 255 pour définir la couleur du robot
// l et L en mm largeur et Longueur du robot.
 
void drawRobot(int x, int y, float z, int r, int g, int b, int l, int L) {
  rectMode(CENTER);
  int largeurRobot = l / 4;
  int longueurRobot = L/ 4;
  fill(r,g,b);
  translate(xToPixel(x), yToPixel(y));
  rotate(z);
  rect(0, 0, largeurRobot,longueurRobot); 
}

void keyPressed() {
  if(key == 'z')
   vy=vmax/framerate;
  else if(key == 's')
   vy=-vmax/framerate;
  else if(key == 'q')
   vx=-vmax/framerate;
  else if(key == 'd')
   vx=vmax/framerate;
  else if(key == 'a')
   vz=-vzmax;
  else if(key == 'e')
   vz=vzmax;
}

void keyReleased() {
    vx=0;
    vy=0;
    vz=0;
}

void drawData() {
  textSize(18);
  fill(0,0,255);
  text("x = " + x, 30,20);
  text("y = " + y, 30,40);
  text("z = " + z, 30,60);
  text("vx = " + vx, 30,80);
  text("vy = " + vy, 30,100);
  text("vz = " + vz, 30,120);
}

Pour tester c'est assez simple : 

  • Téléchargez la version de processing qui vous faut : https://processing.org/download installez le et lancez le. Vous aurez alors un fichier vierge .pde qui s'ouvre. 
  • Copiez y le code ci dessus, et enregistrez le fichier. 
  • Téléchargez l'image .png et mettez là dans le dossier qui vient d'être crée en enregistrant le fichier.pde. 
  • Cliquez sur le bouton " play " en haut à gauche, la fenêtre de l'appli s'ouvre et vous pourrez alors déplacer le "robot " avec le clavier.

N'hésitez pas à tester et à modifier. 
Si ça vous intéresse / que vous l'utilisez, n'hésitez pas à commenter ce post avec votre application / vos modifications. 
Je pourrais éventuellement également proposer plus de chose sur cette base d'application si il y a des gens qui ont des idées ou des besoins...

En espérant que ça puisse donner quelques idées à certains. 

 


Si mon commentaire vous a plus laissez nous un avis  !  :thank_you:

Nouveau sur Robot Maker ? 

Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope  aux articles,  à la boutique  et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être ! 
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!

 

Les réalisations de Mike118  

 

 

 


#2 Mike118

Mike118

    Staff Robot Maker

  • Administrateur
  • PipPipPipPipPip
  • 9 934 messages
  • Gender:Male
  • Location:Anglet
  • Interests:Robotique, Entrepreneuriat, Innovation, Programmation, Résolution de problème, Recherche de solutions, Mécanique, Electronique, Créer, Concevoir

Posté 20 avril 2022 - 02:36

Du coup petit update, 

// Code réalisé par Mike118 de www. robot-maker.com.
// Ce sketch peut servir de base pour un simulateur de robot pour la coupe de france de robotique
// la table est orienté de sorte à ce que l'axe de x soit la longeur de la table ( 3000mm )
// l'axe des y est la largeur de la table (2000mm) et l'origine au milieu bas.
// x € [ -1500, 1500] et y € [0, 2000]  et z en Radian
// Permet d'afficher la position du robot ainsi que 200 pts lidar
// Envoyez des trames séries de la forme P:x,y,z pour déplacer le robot avec un saut de ligne à la fin
// Envoyez des trames séries de la forme L:x0,y0,x1,y1,...x199,y199 avec un saut de ligne à la fin
// Branchez une arduino avec le code d'exemple arduino fournis pour tester
// Note: il ne faut avoir qu'un seul port com branché sur l'ordinateur avec ce code...

PImage table;
int framerate = 25;

class Point {
  public short coords[] = new short[2];
  
  public Point(int x, int y) {
   this.coords[0] = (short)x;
   this.coords[1] = (short)y;
  }
 
  public short x() {
    return this.coords[0];
  }
  
  public short y() {
    return this.coords[1];
  }
 
  public void x(int val) {
    this.coords[0]=(short)val;
  }
  
  public void y(int val) {
    this.coords[1]=(short)val;
  }
} 

Point [] lidar = new Point[200];


// Dimensions de la table en mm
int tablex = 3000;
int tabley = 2000;

// Coordonnées du robot en mm
int x=-1400;
int y=1200;
float z=0;     // Angle du robot en radian

import processing.serial.*;
String[] serialports;
Serial rx;

void setup() {
  noStroke();
  size(1200, 700);
  frameRate(framerate);
  table = loadImage("tablegrille.png"); // 750 * 500 pixel  1 pixel = 4mm
  serialports = Serial.list();
  println(serialports.length);
  println(serialports);

  for (int i=0; i < 200; i++) {
    lidar[i] = new Point(0, 0);
  }

  if ( serialports.length == 1) {
    rx = new Serial(this, Serial.list()[0], 115200);
    rx.bufferUntil('\n');
  } else
  println("error");
}


void draw() {
  background(0);
  println(frameCount + ": " +  key);
  imageMode(CENTER);
  image(table, width/2, height/2);
  drawData() ;
  int l = 180;  // Largeur du robot
  int L= 180;   // Longuer du robot
  drawRect(x, y, z, 255, 255, 0, 180, 180);

  for (int i = 0; i < 200; i++) {
    drawRect(lidar[i].x(), lidar[i].y(), 0, 255, 0, 0, 12, 12);
  }
}


// Fonctions de conversions de position en mm en postion en pixels

int xToPixel(int x) {
  return x/4 + width/2 ;  // /4 car 1 pixel = 4mm
}

int yToPixel(int y) {
  return -y/4 + height -100; //  /4 car 1 pixel = 4mm et -100 pour la bordure de noir
}

// drawRect(int x, int y, float z, int r, int g, int b, int l, int L)
// x y position en mm
// z angle en radian
// r g b, entier entre 0 et 255 pour définir la couleur du robot
// l et L en mm largeur et Longueur du rectangle.

void drawRect(int x, int y, float z, int r, int g, int b, int l, int L) {
  pushMatrix();
  rectMode(CENTER);
  int largeurRobot = l / 4;
  int longueurRobot = L/ 4;
  fill(r, g, b);
  translate(xToPixel(x), yToPixel(y));
  rotate(z);
  rect(0, 0, largeurRobot, longueurRobot);
  popMatrix();
}

void drawData() {
  textSize(18);
  fill(0, 0, 255);
  text("x = " + x, 30, 20);
  text("y = " + y, 30, 40);
  text("z = " + z, 30, 60);
}


void serialEvent(Serial thisPort) {
  String message = thisPort.readString();
  message = trim(message);
  println(message);
  String[] dataMessage = split(message, ":");
  
  if (dataMessage.length == 2) {
    String[] valuesMessage = split(dataMessage[1], ",");
    if (dataMessage[0].charAt(0) == 'L') {
      if (valuesMessage.length >= 400) { 
        for (int i=0; i<200; i++) {
          lidar[i].x((short)int(valuesMessage[2*i]));
          lidar[i].y((short)int(valuesMessage[2*i + 1]));
        }
      }
    } else if (dataMessage[0].charAt(0) == 'P') {
      x = (short)int(valuesMessage[0]);
      y = (short)int(valuesMessage[1]);
      z = float(valuesMessage[2]);
    }
  }
}

et pour le tester vous pouvez utiliser ce petit code arduino : 

 

// Code réalisé par Mike118 de www. robot-maker.com.
// Code de test pour valider le fonctionnement du simulateur 
// Permet d'envoyer une trame de position de robot ainsi que 200 pts lidar
// Trames séries de la forme P:x,y,z avec un saut de ligne à la fin pour la position du robot
// Trames séries de la forme L:x0,y0,x1,y1,...x199,y199 avec un saut de ligne à la fin pour les 200pts lidar.
 
#define VITESSE 16
int x = -1400;  // Position en mm
int y = 1200;   // Position en mm
float z = PI/4; // Angle en Radian
int deltax = VITESSE;
int deltay = VITESSE;

typedef struct {
  union {
    struct {
      int16_t x;
      int16_t y;
    };
    int16_t coordonnees[2];
    uint8_t bytes[4];
  };
} Point;


Point lidar[200] = {{0, 0}};

void setup() {
  Serial.begin(115200);
  for (uint8_t i = 0; i < 60; i++) {
    lidar[i].x = i * 50 - 1500;
    lidar[i].y = 0;
  }
  for (uint8_t i = 60; i < 100; i++) {
    lidar[i].x = 1500;
    lidar[i].y = (i - 60)* 50;
  }
  for (uint8_t i = 100; i < 160; i++) {
    lidar[i].x = 1500 -(i - 100)* 50 ;
    lidar[i].y = 2000;
  }
  for (uint8_t i = 160; i < 200; i++) {
    lidar[i].x = -1500;
    lidar[i].y = 2000 - (i - 160)* 50;
  }
}

void loop() {
  if(x > 1250) {
    deltax = -VITESSE;
  } else if(x < -1250) {
    deltax = VITESSE;
  }

  if(y > 1750) {
    deltay = -VITESSE;
  } else if(y < 250) {
    deltay = VITESSE;
  }
  x+= deltax;
  y+= deltay;
 
  Serial.println((String) "P:" + x + "," + y + "," + z);

  Serial.print("L:");
  for (uint8_t i = 0; i < 200; i++) {
    Serial.print(lidar[i].x);
    Serial.print(',');
    Serial.print(lidar[i].y);
    Serial.print(',');
  }
  Serial.println();
}

Bien entendu c'est un code d'exemple fonctionnel mais qui pourrait être largement amélioré.
Le protocole d'échange d'informations via le port série pourrait être largement améliorer pour envoyer les données sous formes d'octets plutôt qu'en chaîne de  caractère par exemple ... 
On peut aussi imaginer pouvoir envoyer des trames au robot en appuyant sur certaines touches du clavier par exemple si besoin...

 

Maintenant à vous de jouer, vous pouvez de modifier ce code arduino et le code processing pour afficher les points de votre lidar plutôt que les points générés par défaut par exemple!


Si mon commentaire vous a plus laissez nous un avis  !  :thank_you:

Nouveau sur Robot Maker ? 

Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope  aux articles,  à la boutique  et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être ! 
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!

 

Les réalisations de Mike118  

 

 

 


#3 zavatha

zavatha

    Habitué

  • Membres
  • PipPip
  • 233 messages
  • Gender:Male

Posté 21 avril 2022 - 01:34

Salut,

 

J'avais eu la même problématique lors du développement de mon projet RES (qui attends toujours dans sa boîte d'être terminé d'ailleurs...) : 

les trames de commande du robot sont envoyées par l'appli windows au raspberry Pi en wifi sous forme de chaînes.

J'avais fait ce choix par facilité car beaucoup d'autres choses à assimiler avant...

 

Mais je pense comme toi qu'une structure simple pré déterminée transmise sous forme de byte[] devrait permettre de fluidifier la comm entre devices et d'éviter (peut être) le recours à un système de checksums...

 

c'est un champ à explorer... intéressant mais un poil (trop) chronophage dans mon cas :P

 

++

Zav





Répondre à ce sujet



  



0 utilisateur(s) li(sen)t ce sujet

0 members, 0 guests, 0 anonymous users