Aller au contenu


Photo
- - - - -

Bien paramétrer un mouvement simple et le complexifier.

Processing

  • Veuillez vous connecter pour répondre
2 réponses à ce sujet

#1 bvking

bvking

    Membre occasionnel

  • Membres
  • Pip
  • 98 messages

Posté 05 avril 2022 - 08:33

Bonjour à toutes et tous ;)

 

Pour mon installation artistique, j’aimerais à partir du mouvement d’un point tournant à vitesse constante, pouvoir faire que 9 autres points suivent le premier avec des décalages temporels et spatiaux.

Cette partie fonctionne :yahoo: . Merci Mike.

 

Maintenant, j'aimerais l'essayer, non plus à partir d’un point tournant, mais d'un point qui oscille de 0 à 180°, comme un pendule et à vitesse constante.

Peut on simplement changer l'équation du programme? celle commentée  // position du point de depart + vitesse * phi constant ==> ici vitesse du point phases[0] est constante

 

Merci  :king:

String debug =""; 

// MANAGE PERSPECTIVE
import peasy.*;

// change these for screen size
float w = 1000;
float h = 800;

// don't change these
float w2 = w / 2;
float h2 = h / 2;

int frameRatio = 25; // nombre d'image/seconde ou nombre de fois que la bouche principale du programme void draw() tourne en un seconde
int nbBall = 10;
int nbMaxDelais = 2000;

float [][] phases = new float[nbBall][nbMaxDelais];

void setup() {
  new PeasyCam(this, 2000);
  frameRate(frameRatio);  
  for (int i = 0; i < nbBall; i++) {
    for (int j = 0; j < nbMaxDelais; j++)
      phases[i][j] = PI;
  }
} 

public void settings() {
  size(600, 600, P3D);
} 

void draw() { 
  println(frameCount + ": " + ( debug ));
  background(0);
  translate(width/2, -height/2, -1000);// To set the center of the perspective
  rotate(-HALF_PI ); //TO change the beginning of the 0 (cercle trigo) and the cohesion point to - HALF_PI 

    phases[0][frameCount % nbMaxDelais]= PI + (frameCount / 5.0) *  cos (1000 / 500.0);  // position du point de depart + vitesse * phi constant  ==> ici vitesse du point phases[0] est constante
  //point O tourne dans le sens anti-horaire à vitesse constante
  
 //   phases[0][frameCount % nbMaxDelais]= TWO_PI + (frameCount / 50.0) *  cos (frameCount / 500.0);  //position du point de depart + vitesse* phase sinusoidale  ==> ici vitesse 0 progresse suivant une sinusoidale
  //point O tourne dans les deux sens à vitesse non constante. Je cherche un mouvement pendulaire 
  
  
  drawBall(0, phases[0][frameCount % nbMaxDelais] ); // affiche le point 0

  for (int i = 1; i < nbBall; i++) {
 //   follow( i-1, i, 20 * i, 0);  // Modifier les deux derniers paramètres : délais et phase 
    follow( i-1, i, 0 , QUARTER_PI);  // ici, le temps que les points mettent à se suivre est nul, donc l'espace entre eux est constant, il est 180/4=45°
    drawBall(i, phases[i][frameCount % nbMaxDelais] );
  }

  /* 
  for(int i = 0; i < nbBall; i++) { //Animation brute sans suivi, juste avec une formule 
   //drawBall(i, PI + (i * frameCount / 50.0) * cos (frameCount / 500.0) );  
  }*/
}

void drawBall(int n, float phase) {
  pushMatrix();
  translate(-w2, -h2, -1000);
  noStroke();
  float side = height*0.15*1/nbBall;
  float rayon = width/2; 
  float x = rayon*cos(phase);
  float y = rayon*sin(phase);
  translate (x, y, 200+(50*5*n));  
  colorMode(RGB, 255, 255, 255);
  fill( 0, 255, 0 ); 
  sphere(side*3);
  popMatrix();
}

void follow( int target, int follower, int delais, float deltaphase) {
  int step = frameCount % nbMaxDelais;
  int followedStep = (step + nbMaxDelais - delais) % nbMaxDelais;
  phases[follower][step] = diffAngle(phases[target][followedStep] + deltaphase, 0);
}

float diffAngle(float angle1, float angle2) { // return the difference angle1 - angle2 between two angle between -PI PI
  float result = angle1 - angle2;
  while (result > PI) {
    result -= 2 * PI;
  }
  while (result < -PI) {
    result += 2 * PI;
  }
  return result;
}


#2 Mike118

Mike118

    Staff Robot Maker

  • Administrateur
  • PipPipPipPipPip
  • 9 963 messages
  • Gender:Male
  • Location:Anglet

Posté 05 avril 2022 - 09:48

tu peux essayer ça : 

 

  float angle = diffAngle(PI + (frameCount / 5.0) *  cos (1000 / 500.0),0);
  
  if(angle > 0 )
    phases[0][frameCount % nbMaxDelais]= angle - HALF_PI ;  // position du point de depart + vitesse * phi constant  ==> ici vitesse du point phases[0] est constante
  else 
    phases[0][frameCount % nbMaxDelais]= 2* PI - angle - HALF_PI;

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 bvking

bvking

    Membre occasionnel

  • Membres
  • Pip
  • 98 messages

Posté 27 avril 2022 - 07:37

 

tu peux essayer ça : 

 

  float angle = diffAngle(PI + (frameCount / 5.0) *  cos (1000 / 500.0),0);
  
  if(angle > 0 )
    phases[0][frameCount % nbMaxDelais]= angle - HALF_PI ;  // position du point de depart + vitesse * phi constant  ==> ici vitesse du point phases[0] est constante
  else 
    phases[0][frameCount % nbMaxDelais]= 2* PI - angle - HALF_PI;

Pardon, j'avais pas dit merci ;)

J'ai re-bossé la fonction pour m'approcher d'une vague qui se décalle de 0 à PI, puis de PI à 0 automatiquement.

 

Voici le programme, pour voir ce que je veux il faut dé-commenter la ligne 139, je te laisse faire pour que tu comprennes l'étape de transformation du mouvement.

String debug =""; 

// MANAGE PERSPECTIVE
import peasy.*;

// change these for screen size
float w = 1000;
float h = 800;

// don't change these
float w2 = w / 2;
float h2 = h / 2;

int frameRatio = 30;
int nbBall = 10;
int nbMaxDelais = 2000;
float pendulairePhaseX;
float pendulairePhaseY;

// Code pour option de follow 
boolean firstFollowingLast = true;
float deltaFollow = PI/180;
boolean firstFollowingStarted = false;

float [][] phases = new float[nbBall][nbMaxDelais];

void setup() {
  new PeasyCam(this, 2000);
  frameRate(frameRatio);  
  for (int i = 0; i < nbBall; i++) {
    for (int j = 0; j < nbMaxDelais; j++)
      phases[i][j] = PI;
  }
} 
public void settings() {
  size(600, 600, P3D);
} 

void draw() { 
  println(frameCount + ": " + ( debug ));
  background(0);
   rotate(- TWO_PI  ); //TO change the beginning of the 0 (cercle trigo) and the cohesion point to - HALF_PI 
  translate(width/2, -height/2, -1000);// To set the center of the perspective

 // **************************    RAPPEL
 //   phases[0][frameCount % nbMaxDelais]= PI + (frameCount / 5.0) *  sin (1000 / 500.0);  // position du point de depart + vitesse * phi constanst  ==> ici vitesse du point phases[0] est constante
  //point O tourne dans le sens anti-horaire à vitesse constante
  
//    phases[0][frameCount % nbMaxDelais]= TWO_PI + (frameCount / 5.0) *  sin (frameCount / 50.0);  //position du point de depart + vitesse* phase sinusoidale  ==> ici vitesse 0 progresse suivant une sinusoidale
  //point O tourne dans les deux sens à vitesse non constante
  // ************************** 
  
   float angle = diffAngle(PI + (frameCount / 4.0) *  cos (1000 / 500.0),0);
   
//**** ci dessous pour avoir le point du fond qui oscille de 0 à 180°
  if(angle > 0 )
    phases[0][frameCount % nbMaxDelais]= (angle - HALF_PI);// position du point de depart + vitesse * phi constant  ==> ici vitesse du point phases[0] est constante

  else 
    phases[0][frameCount % nbMaxDelais]= (2* PI - angle - HALF_PI);//
//****
 //*** drawBall(0, phases[0][frameCount % nbMaxDelais] ); // affiche le point 0. NE PAS AFFICHER SINON IL APPARAIT EN DOUBLE
  
  for (int i = 1; i < nbBall; i++) {
     debug ="Normal follow ";
 //   follow( i-1, i, 20 * i, 0);  // Modifier les deux derniers paramètres : délais et phase 
    follow( i-1, i, 5 , QUARTER_PI/6);  // ici, le temps que les points attendent pour se suivre est de 5 frames, et il faut un espace entre eux de QUARTER_PI/6
    drawBall(i, phases[i][frameCount % nbMaxDelais] );
  
  //***  print ("phases[0] "); print(i); print (" "); print (phases[0] [frameCount % nbMaxDelais] );

  //***  print ("phases[I]  "); print(i); print (" "); print (phases[i] [frameCount % nbMaxDelais] );
  //***  println (" ");
  }
  
  /* 
  for(int i = 0; i < nbBall; i++) { //Animation brute sans suivi, juste avec une formule 
   //drawBall(i, PI + (i * frameCount / 50.0) * cos (frameCount / 500.0) );  
  }*/
  //********************************UTILITE de firstFollowingLast=true or false? je l'ai retiré et je vois pas de différence
 //  if(frameCount > nbMaxDelais/10 && firstFollowingLast == true && abs(diffAngle(phases[0][frameCount % nbMaxDelais],phases[nbBall-1][frameCount % nbMaxDelais])) < deltaFollow ) {
    if(frameCount > nbMaxDelais/10 && abs(diffAngle(phases[0][frameCount % nbMaxDelais],phases[nbBall-1][frameCount % nbMaxDelais])) < deltaFollow ) {
      colorMode(RGB, 255, 255, 255);
     fill( 0, 0, 255 ); 
    println("diffangle" + ": " + diffAngle(phases[0][frameCount % nbMaxDelais],phases[nbBall-1][frameCount % nbMaxDelais]));
    firstFollowingStarted = true;
    debug ="First follow last";
    println (debug);
  }
  
  if(firstFollowingStarted) {
     colorMode(RGB, 255, 255, 255);
     fill( 255, 0, 0 ); 
     debug ="firstFollowingStarted";
    follow(nbBall-1, 0, 5, QUARTER_PI/4);  // Modifier les deux derniers paramètres : délais et phase
   
    drawBall(0, phases[0][frameCount % nbMaxDelais] ); // affiche le point 0
  } 
}

void drawBall(int n, float phase) {
  pushMatrix();
  translate(-w2, -h2, -1000);
  noStroke();
  float side = height*0.15*1/nbBall;
  float rayon = width/2; 

  float x = rayon*cos(phase);
  float y = rayon*sin(phase);
    for (int i = 1; i < nbBall; i++) { // ce for { } est pour contraindre le mouvement à rester sur 180°
    if (x >= PI ) { 
         pendulairePhaseX= map( x, 0, TWO_PI, 1.5*PI, -0.5*PI);
      }
      if (x >= 0 && x < PI ) {
         pendulairePhaseX= map( x, 0, TWO_PI, -0.5*PI, 1.5*PI);
      }
      if (x <= -PI) { 
         pendulairePhaseX= map( x, 0, -TWO_PI, 1.5*PI, -0.5*PI);
      }  
      if (x < 0  && x > -PI) {   
         pendulairePhaseX= map( x, 0, -TWO_PI, -0.5*PI, 1.5*PI );
      }
      
      if (y >= PI ) { 
         pendulairePhaseY= map( y, 0, TWO_PI, 1.5*PI, -0.5*PI);
      }
      if (y >= 0 && y < PI ) {
         pendulairePhaseY= map( y, 0, TWO_PI, -0.5*PI, 1.5*PI);
      }
      if (y <= -PI) { 
         pendulairePhaseY= map( y, 0, -TWO_PI, 1.5*PI, -0.5*PI);
      }  
      if (y < 0  && y > -PI) {   
         pendulairePhaseY= map( y, 0, -TWO_PI, -0.5*PI, 1.5*PI );
      } 
 //   x=pendulairePhaseX; 

    }
//      y=pendulairePhaseY; //si on decommente cette ligne vague se decale petit à petit depuis les deux côtés du mouvement de 180° !!!
  

// translate (x, y, 200+(50*5*n)); // on voit la vague qui se decale petit à petit, chouette, mais sur 360° alors que j'aimerais sur 180°
// translate (pendulairePhaseX, pendulairePhaseY, 200+(50*5*n)); // on voit la vague qui se decale petit à petit, mais sur 90° (à vue de nez)
  translate (x, y, 200+(50*5*n)); // on voit la vague comme j'aimerais si on fait ce qui ait dit à la ligne 139
  translate (100, 100, 200+(50*5*n)); 
  colorMode(RGB, 255, 255, 255);
  fill( 0, 255, 0 ); 
  sphere(side*3);
  popMatrix();
}

void follow( int target, int follower, int delais, float deltaphase) {
  int step = frameCount % nbMaxDelais;
  int followedStep = (step + nbMaxDelais - delais) % nbMaxDelais;
  phases[follower][step] = diffAngle(phases[target][followedStep] + deltaphase, 0); 
}

float diffAngle(float angle1, float angle2) { // return the difference angle1 - angle2 between two angle between -PI PI
  float result = angle1 - angle2;
  while (result > PI) {
    result -= 2 * PI;
  }
  while (result < -PI) {
    result += 2 * PI;
  }
  return result;
}

 

Ensuite j'ai fait une video expliquant la fonction pour faire la "meme chose" d'une autre maniere.

 

https://youtu.be/VDR-ot7tQhs

 

Voila une petite explication écrite de la fonction que j'ai crée .

Comme dans la transformation des points x, y que j'ai faite dans la fonction de MIKE, le mouvement de l'ensemble des points est contraint entre 0 et PI alors que la donnée qui conduit le mouvement paramétrique des phases x, y (suis pas sûr de l’expression) ici, net.phase[i] est bien une phase allant  de 0 à deux PI.  Il faut se dire que les données x y parametrent la position d’un point sur un cercle et moi j’ai fait en sorte de voir ses points de 0 à PI. 
J’explique tous ca jusqu’à 4 min 14 et comment le point deux suit le 11, mais pas tous le temps, ceci implique un joli décalage dans le suivi de la vague.. Apres 4 min 30 pas la peine d’écouter je cherchais à bien paramétrer la vitesse de l’ensemble de points. 
 
A partir de 10 min 13 jusqu’à la fin de la video, le mouvement est celui que je veux, mais j'aimerais qu'il soit possible à 45 frames par secondes et pas à 5 frames par secondes. Pour eviter les à-coups et avoir un mouvement fluide. A 45 frames/secondes, les points se suivent mais le fait qu'ils attendent 200 ms, fait un mouvement d'ensemble saccadé pas beau.
 
Je mets ma fonction ici
 
void formerKeyo() {  print (" circularMov  ");  println (circularMov);
 if (circularMov==false  ){
   memoryi=0;
   for (int i = 2; i < 11; i++) { 
       print ("formerEvent"); print (i);  print (" ") ;print (formerEvent[i]) ;
    if ( millis()>formerEvent[i]+200 && // si le temps est supérieur de 200 ms par rapport à la dernier fois et que le point i+1 est supérieur de 200 pas par rapport au point i
   (((PendularOldLeftVirtualPosition[i] <= PendularLeftVirtualPosition[i+1]+800*0.25) && (PendularLeftVirtualPosition[i]+800*0.25 > PendularLeftVirtualPosition[i+1]) && (PendularOldLeftVirtualPosition[i]< PendularLeftVirtualPosition[i])) ||
    ((PendularOldLeftVirtualPosition[i]+800*0.25 >= PendularLeftVirtualPosition[i+1]) && (PendularLeftVirtualPosition[i]< PendularLeftVirtualPosition[i+1]+800*0.25)&& (PendularOldLeftVirtualPosition[i] > PendularLeftVirtualPosition[i])))
  ){
     memoryi=i;
     formerEvent[i]=millis();  
     net.phase[i+1]= net.oldPhase[i];//      
   }
    else if (millis()<=formerEvent[i]+200){
     memoryi=100*i;
      }
   }
    print ("AVformerEvent"); print (11);  print (" "); println (formerEvent[11]) ;
    if  (millis()>formerEvent[11]+200 && // si le temps est supérieur de 200 ms par rapport à la derniere fois et que le point 11 est supérieur à 200 pas par rapport au point 2
    ((PendularOldLeftVirtualPosition[11] <= PendularLeftVirtualPosition[2]+800*0.25) && (PendularLeftVirtualPosition[11]+800*0.25 > PendularLeftVirtualPosition[2]) && (PendularOldLeftVirtualPosition[11]< PendularLeftVirtualPosition[11]) ||
    ((PendularOldLeftVirtualPosition[11]+800*0.25 >= PendularLeftVirtualPosition[2]) && (PendularLeftVirtualPosition[11]< PendularLeftVirtualPosition[2]+800*0.25)&& (PendularOldLeftVirtualPosition[11] > PendularLeftVirtualPosition[11]))
  )){
     memoryi=11;
     formerEvent[11]=millis();
     net.phase[2]= net.oldPhase[net.size()-1];
     print ("APformerEvent"); print (11);  print (" "); println (formerEvent[11]) ;  
     } 
    else if (millis()<=formerEvent[11]+200){ // si le temps n'est pas supérieur à 200 ms alors laisse les points suivrent leur propre vitesse
     memoryi=12;
      }  
    }    
 }  

Voilà voilà   :drag_10:

Le but est de soit faire en sorte que j'ai ma fonction qui puisse bien attendre un certain temps avant de suivre les points, car elle fonctionne à 5 images secondes et pas à 45 images. Ca fait encore plus saccader le mouvement si je passe de 5 à 45. Je vais filmer un exemple demain.

Je pense qu'il faut que je baisse le temps de suivi au fur et à mesure que j'augmente  le nombre d'image / sec. Bref je vais essayer.

 

Ou réussir à trouver cette vague à partir du programme de Mike, ce qui m'a l'air plus saint et plus simple!  :mr47_05:







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

0 members, 0 guests, 0 anonymous users