Aller au contenu


Photo
- - - - -

Répéter un mouvement et le synchroniser sur un tempo.

Processing

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

#1 bvking

bvking

    Membre occasionnel

  • Membres
  • Pip
  • 98 messages

Posté 17 août 2022 - 05:44

Bonjour,

Pour mon projet de machine artistique, j'ai besoin de sampler un mouvement et le jouer en boucle. Ce sample doit être caler sur le tempo!

Mais, y' a un petit problème, je m'explique:

 

Je dessine un mouvement avec la souris pendant deux secondes.

Il est répété en boucle en commençant exactement sur le début d'une nouvelle seconde.

Le problème est que le nombre d'image par seconde n'est pas constant. 

Des fois, il faut 27 image/sec, des fois 28. 

J'observe donc des décalages. Il faudrait que j'arrive à jouer cette boucle exactement par son début toutes les deux secondes.

Le défaut sur deux secondes est minimale, mais sur 8 secondes j'ai des décalages plus important.

Il faut trouver un moyen d'avoir la même donné toute les deux sec.

 

Merci pour vos contributions.

 

Mon programme ci-dessous. NB pour créer un mouvement mouvement il suffit de presser la souris. Le dessin commencera a être enregistré

au début de la période de deux secondes et exactement au changement de seconde.

//int num = 40; // you need normally 45 frames/s but actually with a 3D setting you  need only 40 frames
int num = 27; // you need normally 30 frames/s but actually with a 3D setting you  need only 26.33 frames
int numberSec = 2;

float mx[] = new float[num*numberSec]; // memorised frame played 
float my[] = new float[num*numberSec]; // 

float rx[] = new float[num*numberSec]; // recorded frame
float ry[] = new float[num*numberSec]; 

int beginTime,endTime,TimeMiddleElapsed,LastTimeMiddleElapsed,LastTimeElapsed;
int frame;
int restartTimer;
float Timer,Timer2;

boolean  mouseRecorded;
boolean synchroMeasure;
boolean beginSampling, endSampling;
int lastLastSec,lastSec,actualSec; 

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

void setup() 
  {
  endSampling= false;
  synchroMeasure= false;
  mousePressed=false;
  mouseRecorded=false;

  frameRate (30);
  
  noStroke();
  fill(255, 0, 0, 50); 
  println("Start Drawing!");
  }
  
void draw(){  
  
     if  (lastLastSec!=lastSec){         
     print( "                 SAMPLING MODE " ) ;  print( " LASTLASTSEC " ) ; print( lastLastSec ) ; print( " LASTLAST%2 " ); print( lastLastSec%2 );
     print( " ACTUAL " ) ; print( actualSec ) ; print( " ACTUAL " ) ; print( actualSec ) ; print( " ACTUAL " ) ; println( actualSec ) ;
       
     lastLastSec=lastSec;
     synchroMeasure=true;
     background(40, 40, 255);  
     
     }
     else synchroMeasure=false;
    
     if  (actualSec!=lastSec){
         lastSec=actualSec;   
     }
         
    actualSec = second()%(numberSec+1);  // Values from 0 - x number of secondes
    samplingMovement(numberSec);
  }
  
void samplingMovement(float timeSec) {

     if (mousePressed==true)
      {
       mouseRecorded=true; 
     }  
    
      if(synchroMeasure==true && lastLastSec>=numberSec && lastLastSec<=numberSec){
      beginSampling=false;
     }    

     if (mouseRecorded==true  && synchroMeasure==true && lastLastSec<=0// 
     ) {
       print (" Restart Record ");  print (" Restart Record ");  println (" Restart Record ");
    mouseRecorded=false;
    endSampling= false;
    beginSampling=true;
    frame = 0; //
     }
     
    frame=frame+1;
     
    int i = int(frame%(num*timeSec+0)); // number of datas record = number of frame/ s  multipled by secondes
   
    if( beginSampling==true ) // frame>=0 &&
    {  
    rx[i] = mouseX;
    ry[i] = mouseY;
    mx[i] = rx[i];
    my[i] = ry[i];
    fill(255, 0, 0, 50); 
    circle(rx[i], ry[i], 10); 
    if (frame%1<=0) {
    print (" frame "); print (frame); print (" ry "); print (i); print ("  "); println (ry[i]);   // 
    }   
   }
   
    if( endSampling==true ) // begin to replay for 2 sec . If I Add frame>num*timeSec+1, there is no effect   
    {
    circle(mx[i]+400, my[i], 10);  
    if (frame%1<=0) {
    print (" frame "); print (frame); print (" ry "); print (i); print ("  "); println (ry[i]);   // 
    } 
     } 
    if(synchroMeasure==true && lastLastSec>=timeSec && lastLastSec<=timeSec){ // important to put condition here! or on the of the main loop
    endSampling=true;
   }   
}


#2 Mike118

Mike118

    Staff Robot Maker

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

Posté 19 août 2022 - 03:28

Il te faut avoir toujours le même nombre d'image à chaque fois et régler en premier lieu ton problème d'acquisition. 
+> Toujours le même nombre d'image, toujours le même intervalle entre les prises ...


Si tu n'es pas assez précis pour toujours avoir le même nombre d'image à l'image près, afin de lisser un peu "l'erreur" tu peux décider de " sur échantillonner " et de toujours prendre le même nombre de frame par secondes parmi l'ensemble de informations récoltées.

Exemple : Imaginons que tu ne souhaites que avoir tout le temps 28 images par secondes. 

Tu peux décider d'en prendre tout le temps 56 images par secondes et de sauter une frame /2  dans ton replay en commençant par la première ...

Si il s'avère à un moment donné que ton process d'acquisition te done 55 images au lieu de 56 vu que de toute façon tu ne prends pas la dernière image ça ne te changera rien ...
Et si tu as 57 images au lieu de 56 tu peux toujours décider de "jeter la première " et faire comme si tu en avais que 56 ... 

Ainsi les décalage temporelle sont que de la moitié de ce que ça pourrait être si tu prenais tout le temps 29 images et que tu en gardais toujours que 28 ... 


Après une autre approche peut être d'interpoler les données, c'est valable surtout si tu n'arrives pas à avoir un laps de temps fixe entre deux prises de mesures ...


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é 20 août 2022 - 12:37

J'ai commencé à travailler sur ta solution, mais je me suis dit que je pouvais pas changer le nombre d'images/seconde pendant que j'enregistre mes données.

En fait mon programme fait varier d'autres positions avec un frameRate de 30. Si je passe à 60, toutes ses positions vont aller deux fois plus vite.

Aussi, je peux ré adapter mon programme global mais ça peut être compliqué...

En fait il ne faudrait pas dépendre du frameCount mais du temps reel. 

Il faudrait par exemple toutes les 25 millisecondes enregistrer la position partir de la fonction millis (). Est ce possible?

Ensuite pour jouer ces données exactement sur le tempo, il faudra surement faire des interpolations pour"relier les données au moment de la pulsation".

Donc là, j'ai besoin de  tes lumières!  :clapping:

 

Je mets quand meme les modifications, car pour la presentation de ma machine la solution avec les frame peut suffire, mais en fin de compte je devrais ne pas dépendre 

du frameRatio. Car si je décidais d'augmenter ou baisser le frameRatio, j'aimerais quand meme garder la meme défilement des positions. La meme vitesse en fait. :king: 

 
//int num = 40; // you need normally 45 frames/s but actually with a 3D setting you  need only 40 frames
//int num = 27; // you need normally 30 frames/s but actually with a 3D setting you  need only 26.33 frames
int num = 58; // with  frameRate(60) we have 58 frames/s but actually with a 3D setting 
int numberSec = 2;

float mx[] = new float[num*numberSec]; // position X memorised 
float my[] = new float[num*numberSec]; // 

float rx[] = new float[num*numberSec]; // position X recorded 
float ry[] = new float[num*numberSec]; 

float doubleMx[] = new float[num*numberSec]; // position X memorised 
float doubleMy[] = new float[num*numberSec]; // 

float doubleRx[] = new float[num*numberSec]; // position X recorded 
float doubleRy[] = new float[num*numberSec]; 

int beginTime,endTime,TimeMiddleElapsed,LastTimeMiddleElapsed,LastTimeElapsed;
int frame;
int frameRatio;
int doubleFrame;
int restartTimer;
float Timer,Timer2;

boolean  mouseRecorded;
boolean synchroMeasure;
boolean beginSampling, endSampling;
int lastLastSec,lastSec,actualSec; 

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

void setup() 
  {
  endSampling= false;
  synchroMeasure= false;
  mousePressed=false;
  mouseRecorded=false;
  
  frameRatio=2;
  frameRate (30*frameRatio);
//  num=num* frameRatio; // it doesn't work
  
  
  noStroke();
  fill(255, 0, 0, 50); 
  print("Start Drawing ! The number of frame is "); println ( num );
  }
  
void draw(){  
  
     if  (lastLastSec!=lastSec){         
     print( "                 SAMPLING MODE " ) ;  print( " LASTLASTSEC " ) ; print( lastLastSec ) ; print( " LASTLAST%2 " ); print( lastLastSec%2 );
     print( " LASTSEC " ) ; print( lastSec) ; print( " ACTUAL " ) ; print( actualSec ) ; print( " ACTUAL " ) ; println( actualSec ) ;
       
     lastLastSec=lastSec;
     synchroMeasure=true;
     background(40, 40, 255);  
     
     }
     else synchroMeasure=false;
    
     if  (lastSec!=actualSec){
         lastSec=actualSec;   
     }
         
    actualSec = second()%(numberSec+1);  // Values from 0 - x number of secondes
    samplingMovement(numberSec);
  }
  
void samplingMovement(float timeSec) {

     if (mousePressed==true)
      {
       mouseRecorded=true; 
     }  
    
      if(synchroMeasure==true && lastLastSec>=numberSec && lastLastSec<=numberSec){
      beginSampling=false;
     }    

     if (mouseRecorded==true  && synchroMeasure==true && lastLastSec<=0// 
     ) {
       print (" Restart Record ");  print (" Restart Record ");  println (" Restart Record ");
    mouseRecorded=false;
    endSampling= false;
    beginSampling=true;
    frame = 0; //
    doubleFrame = 0; //
     }
     
    if (frame%2==0){
    doubleFrame= doubleFrame+1;  
    }
    
    frame=frame+1;
      
  
     
    int i = int(frame%(num*timeSec+0)); // number of datas record = number of frame/ s  multipled by secondes
    int j = int(doubleFrame%(num*timeSec*2)); // number of datas record = number of frame/ s  multipled by secondes
      
     if( beginSampling==true ) // frame>=0 &&
    {  
    rx[i] = mouseX;
    ry[i] = mouseY;
    mx[i] = rx[i];
    my[i] = ry[i];
    fill(255, 0, 0, 50); 
    circle(rx[i], ry[i], 10); 
    if (frame%1<=0) {
    print (" frameRECi "); print (frame); print (" ry "); print (i); print ("  "); println (ry[i]);   // 
    }   
   }
    if( beginSampling==true ) // frame>=0 &&
    {  
    doubleRx[j] = mouseX;
    doubleRy[j] = mouseY;
    doubleMx[j] = doubleRx[j]-20;
    doubleMy[j] = doubleRy[j]-20;
    fill(255, 50, 50, 50); 
    circle(doubleMx[j], doubleMy[j], 10); 
    if (frame%1<=0) {
    print (" frameRECj "); print (doubleFrame); print (" Ry "); print (j); print ("  "); println (doubleRy[j]);   // 
    }   
   }
    
    if( endSampling==true ) // begin to replay for 2 sec . If I Add frame>num*timeSec+1, there is no effect   
    {
    circle(mx[i]+400, my[i], 10);  
    if (frame%1<=0) {
    print (" frameMEM "); print (frame); print (" my "); print (i); print ("  "); println (my[i]);   // 
    } 
     } 
    if(synchroMeasure==true && lastLastSec>=timeSec && lastLastSec<=timeSec){ // important to put condition here! or on the of the main loop
    endSampling=true;
   }   
} 


#4 bvking

bvking

    Membre occasionnel

  • Membres
  • Pip
  • 98 messages

Posté 20 août 2022 - 07:18

Voila comment échantillonner un mouvement et le jouer en boucle.

Maintenant je dois le synchroniser à la seconde

boolean bRecording = false;



class Sample {

  int t, x, y;

  Sample( int t, int x, int y ) {

    this.t = t;  this.x = x;  this.y = y;

  }

}



class Sampler {

  ArrayList<Sample> samples;

  int startTime;

  int playbackFrame;

  Sampler() {

    samples = new ArrayList<Sample>();

    startTime = 0;

  }

  void beginRecording() {

    samples = new ArrayList<Sample>();

    startTime = millis();

    playbackFrame = 0;

  }

  void addSample( int x, int y ) {

    samples.add( new Sample( millis() - startTime, x, y ) );

  }

  int fullTime() {

    return ( samples.size() > 1 ) ? 

      samples.get( samples.size()-1 ).t : 0;

  }

  void beginPlaying() {

    startTime = millis();

    playbackFrame = 0;

    println( samples.size(), "samples over", fullTime(), "milliseconds" );

  }

  void draw() {

    int now = (millis() - startTime) % fullTime();

    if( now < samples.get( playbackFrame ).t ) playbackFrame = 0;

    while( samples.get( playbackFrame+1).t < now )

      playbackFrame = (playbackFrame+1) % (samples.size()-1);

    Sample s0 = samples.get( playbackFrame );

    Sample s1 = samples.get( playbackFrame+1 );

    float t0 = s0.t;

    float t1 = s1.t;

    float dt = (now - t0) / (t1 - t0);

    float x = lerp( s0.x, s1.x, dt );

    float y = lerp( s0.y, s1.y, dt );

    circle( x, y, 10 );

  }

}



Sampler sampler;



void setup() {

  size( 800, 800, P3D );

  sampler = new Sampler();

}



void draw() {

  background( 0 );

  if( bRecording ) {

    circle( mouseX, mouseY, 10 );

    sampler.addSample( mouseX, mouseY );

  } else {

    if( sampler.fullTime() > 0 )

      sampler.draw();

  }

}



void mousePressed() {

  bRecording = true;

  sampler.beginRecording();

}



void mouseReleased() {

  bRecording = false;

  sampler.beginPlaying();

}






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

0 members, 0 guests, 0 anonymous users