Aller au contenu


Contenu de bvking

Il y a 95 élément(s) pour bvking (recherche limitée depuis 29-avril 13)



#118946 Tige creuse Vs barre carré creuse ? carbone et télescopique ?

Posté par bvking sur 05 juillet 2023 - 08:59 dans Mécanique

Helio.  :yahoo:

Je voudrais faire télescopique pour des raisons mécaniques et de modularités.

Moins les profils sont grands, moins je dois avoir de couple à exercer sur mon système de LED. 

Avec un format plus petit de profilés je pourrais mettre des systèmes de LED plus lourd à l'avenir.

Aussi j'aimerais que ce soit pratique à transporter car je compte installer ma machine dans divers festivals.

 

Alors j'ai pensé à un système télescopique en encastrant un petit  profilé de 6*6 mm dans un grand profilé au diamètre interne de 8.5 mm

Ce dernier ayant un rayon de 4.25 mm avec Pythagore l' hypotenuse mesure 6.01 mm.

Donc j'aurai un jeu de 0.01 mm. 

Une fois que j'aurais rentré le petit profilé dans l'autre j'aurai du mal à le ressortir mais c'est vraiment pas grave.

Je serai certain de la raideur de la perche créée et de sa legerté. 

Cela vous semble une bonne idée ou y'a t'il plus simple?

 

Par exemple fixer à l'axe moteur un tube carré creux ou circulaire en aluminium de 55 cm de longueur. Puis encastrer un profilé en carbone de 50 cm de longueur dans le tube carré ou circulaire ?

 

Sachant que une longueur de 1 mètre me suffit et que je ne veux pas dépasser une masse de 180 g.

( en fait je vais acheter des moteurs qui vont soutenir jusqu'a 2.2 N .m soit 224 g.m )

 

J'ai vu une perche télescopique pour un micro (donc supportant une masse lourde) sur Amazon qui va jusqu'à 3 metres et pese 260 g. Mais elle est donc trop lourd et un peu cher 30 euros

https://www.amazon.fr/Dextension-Microphone-Réglables-Interface-Transport/dp/B0B2VZ53R4/ref=sr_1_118?keywords=perche+micro&qid=1688540220&sr=8-118




#118944 Tige creuse Vs barre carré creuse ? carbone et télescopique ?

Posté par bvking sur 04 juillet 2023 - 09:18 dans Mécanique

Yep,

Les profiles que j'ai vus sont des carrés de 10mm et ont une diamètre interne de 8.5 mm. On note 10*10*8.5

J'ai calculé la taille d'un carré que l'on peut mettre dans un cercle de 8.5 mm.

On peut mettre un carré de 6.01 mm exactement.
Donc normalement, je pourrais mettre un petit profile 6*6*5 dans un gros de 10*10*8.5.
Il faudra peut etre forcer un peu puis mettre une vis une rondelle et un boulon.
Sinon le vendeur me propose des tube de 3 mm d'épaisseur mais je suis pas sûr qu'ils ne vont pas osciller si je passe de 0 à 360° en une seconde et que je m'arrête.
Bref j'hésite, ou alors je fabrique une antenne télescopique moi meme?
Qu'en pensez vous?
 
voici le lien des profiles carrés
et le lien des tubes de 3 mm d'épaisseur qui peuvent peut etre tout simplement faire le travail



#118942 Tige creuse Vs barre carré creuse ? carbone et télescopique ?

Posté par bvking sur 04 juillet 2023 - 06:34 dans Mécanique

Les tubes PVC en 30mm ou 40mm sont assez rigides.

Ils peuvent être assemblés assez facilement, c'est leur avantage.

 

Une petite photo aiderait beaucoup à la compréhension du problème.

en fait je viens d'acheter des tubes carrés en carbones pultrudés pour avoir une bonne rigidité.

Ils vont peser 64 g au lieu de 100 g.

 

J'espere trouver un système télescopique de tubes carrés ou hexagonaux à l'avenir. Si vous avez une suggestion?




#118940 Tige creuse Vs barre carré creuse ? carbone et télescopique ?

Posté par bvking sur 04 juillet 2023 - 01:54 dans Mécanique

Merci Oracid,

sur cette video on voit les moteurs auxquelles sont accrochés des barres plates en aluminuim

Tout fonctionne car elle ne mesure que 50 cm. Et le systeme de LED pese 15 grammes ici.

 

J'ai peur que des tubes PVC soient trop flexibles avec une masse de 35 grammes au bout de la barre de 70cm.

Aussi je ne dois pas dépasser une largeur de barre de plus 10 mm pour des raisons esthétiques.

 




#118936 Tige creuse Vs barre carré creuse ? carbone et télescopique ?

Posté par bvking sur 04 juillet 2023 - 12:32 dans Mécanique

Bonjour,

 

Je fais tourner des barres en L en alu de 100 g et 100 mm.  La barre n'est pas fixée au moteur en son centre mais à 70/30 cm.

Au bout des 70 cm est fixée une masse de 15 g. Cette masse est un sytème de LED.

Les moteurs pas à pas peuvent soutenir un couple de 1.2 N.m soit 122 g/m , si je ne m'abuse. 

 

Sans faire de calcul, la masse de ma barre est trop lourde. Je l'ai choisie en L pour qu'elle soit rigide.

Existent-ils des tiges ou barres creuses que je puisse assembler avec des bagues? ou encore mieux télescopiques? ou plus simplement de un mètre ? (que je découperai ensuite)

 

Je veux garder la dysymetrie 70/ 30 ou 80/20 ou 90/10 (selon que le moteur puisse supporter) pour fixer un bloc de pile du coté des 20 cm pour alimenter à l'autre bout de la tige le système de LED.

 

Grand merci pour vos suggestions.

Benj ;)

 

 

 

 

 




#118147 Interpolation à partir d'un pseudo cercle.

Posté par bvking sur 24 mars 2023 - 01:02 dans Projets logiciels, web, ou simulations

Hello! resultat parfait bientôt! 

Cool on peut faire un pseudo cercle, s'arrêter avant ou aller un peu plus loin que le point de départ et le mouvement se répète parfaitement!
Mais ceci est vrai si on commence le mouvement sur la partie gauche du cercle trigo! Pas depuis la partie droite.
J'ai mis des lignes pour repérer le point de départ de l'enregistrement, qui d'ailleurs commence des qu'on clique sur la sourie et s'arrête au bout de deux secondes.

 

Capture d’écran 2023-05-14 à 20.10.28.png
 
Si tu commences à faire le mouvement depuis la premiere ligne jusqu’a la deuxième et un peu plus, ton programme fonctionne , le mouvement tourne en boucle.
Mais si je pars  de la deuxième ligne, comme sur le screen shot  et que je m’arrête à la troisième et un peu plus ça ne fonctionne pas .
Peux tu corriger ce problème , stp ? :thank_you: 
 

int actualSec,lastSec,measure,measureToStartRecording;
boolean bRecording = false;
boolean mouseRecorded =  true;
float movementInterpolated, angleToInterpolate;
int numberOfSample;

//--------------------        method of interpolation to return the position of (rotation) by adding modulo
float mlerp(float x0, float x1, float t, float M ){
   float dx = (x1 - x0 + 1.5*M) % M - 0.5*M;
   return (x0 + t * dx + M) % M;
}

class Sample {
int t;
float x, y;
Sample( int t, float x, float y ) {
this.t = t; this.x = x; this.y = y;
}
}

class Sampler {

ArrayList<Sample> samples;
ArrayList<Sample> samplesModified;
int startTime;
int playbackFrame;

Sampler() {
samples = new ArrayList<Sample>();
samplesModified = new ArrayList<Sample>();
startTime = 0;
}
void beginRecording() {
samples = new ArrayList<Sample>();
samplesModified = new ArrayList<Sample>();
playbackFrame = 0;
}
void addSample( float x, float y ) { // add sample when bRecording
int now = millis();
if( samples.size() == 0 ) startTime = now;
samples.add( new Sample( now - 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" );
if(samples.size() > 0){
  numberOfSample=samples.size();
  
float deltax = samples.get(0).x - samples.get(samples.size()-1).x;
float deltay = samples.get(0).y - samples.get(samples.size()-1).y;
float sumdist = 0;

for(int i = 0; i < samples.size() - 1; i++) {
sumdist += sqrt((samples.get(i).x - samples.get(i +1 ).x)*(samples.get(i).x - samples.get(i +1 ).x) + (samples.get(i).y - samples.get(i +1 ).y)*(samples.get(i).y - samples.get(i +1 ).y));
}
samplesModified.add( new Sample(samples.get(0).t, samples.get(0).x , samples.get(0).y ) );
float dist = 0;
for(int i = 0; i < samples.size() - 1; i++) {
dist += sqrt((samples.get(i).x - samples.get(i +1 ).x)*(samples.get(i).x - samples.get(i +1 ).x) + (samples.get(i).y - samples.get(i +1 ).y)*(samples.get(i).y - samples.get(i +1 ).y));
samplesModified.add( new Sample(samples.get(i+1).t, (float) (samples.get(i +1).x + (dist * deltax) / sumdist), (float) (samples.get(i+1).y +( dist * deltay )/ sumdist)) );
print(samples.get(i).x);
print(",");
print(samples.get(i).y);
print(",");
print( " good data x " + samplesModified.get(i).x);
print(",");
print( " good data y " + samplesModified.get(i).y);
println("");
}
}
}

 void draw() {
stroke( 255 );
//**RECORD
beginShape(LINES);
for( int i=1; i<samples.size(); i++) {
vertex( samplesModified.get(i-1).x, samplesModified.get(i-1).y ); // replace vertex with Pvector
vertex( samplesModified.get(i).x, samplesModified.get(i).y );
}
endShape();
//**ENDRECORD

//**REPEAT
int now = (millis() - startTime) % fullTime();
if( now < samplesModified.get( playbackFrame ).t ) playbackFrame = 0;
while( samplesModified.get( playbackFrame+1).t < now )
playbackFrame = (playbackFrame+1) % (samples.size()-1);
Sample s0 = samplesModified.get( playbackFrame );
Sample s1 = samplesModified.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 );  // interpolation without modulo
//float y =lerp( s0.y, s1.y, dt ); // 

float x =mlerp( s0.x, s1.x, dt, TWO_PI ); // interpolation with modulo, it's better
float y =mlerp( s0.x, s1.x, dt, TWO_PI );

movementInterpolated = y ;
text (" mov " +  (movementInterpolated) , 100, 500);
fill (255,255,255);
circle ( 100* cos (movementInterpolated)+200, 100*sin (movementInterpolated)+200, 20);
stroke(255);
 }
}

Sampler sampler;

void setup() {  
  size( 800, 800, P3D );
  frameRate(30); // when size is set as P3D (3 dimension) we have 27 or 28 frame (loop) per seconde
  sampler = new Sampler(); 
  mouseY= height/2;
}

void draw() {
  background(50);
   for (int i=0; i<=8; i++ ){ 
    stroke(2);
  line (0, height/8*i, width, height/8*i); // horizon
  line (width/8*i, 0, width/8*i, height); // vertical

  }
  textSize (20);
   //----------------------------------------
  angleToInterpolate = (float) map (mouseY, 0, 200, 0, TWO_PI)%TWO_PI; 
  fill( 100, 0, 0);
  circle ( 100* cos (angleToInterpolate)+200, 100*sin (angleToInterpolate)+200, 20); 
  //----------------------------------------
  pushMatrix();
  translate(width/2, height/2);
  rotate(angleToInterpolate);
  translate(28, 0);
  rect(-30, -5, 60, 10);
  popMatrix();
  //----------------------------------------
  ellipse(width/2, height/2, 5, 5);
  text( " repeted  " +nf (movementInterpolated, 0, 2)  + " original " +nf (angleToInterpolate,0,2 ),width/2, height/4);
//  text( " repeted  " +nf (movementInterpolated, 0, 2) , 10, 0);
  textSize (20);
    /*
      for(int i = 0; i < samples.size() - 1; i++) {
       text (" angleModif " +    sampledModifiedChecking[i], 0, 100+ 20*i);
       text (" angleModif " + samplesModified.get(i).x, 100+ 20*i);
      }
    */

 if  (actualSec!=lastSec){
       lastSec=actualSec;
       measure++;
   }
   
  text (measure, 100, 100 );
  actualSec =(int) (millis()*0.001);  // 

  activeSampling();
  stopSampling();
  
  if( bRecording) { // draw circle
 //   circle( mouseX, mouseY, 10 );
 //   sampler.addSample( mouseX, mouseY );
     textSize(100);
     fill (0, 255, 0);
     text (measure, 200, 100 );
  sampler.addSample( angleToInterpolate, angleToInterpolate );
  }
  
  else {    
  if( sampler.fullTime() > 0 )
        sampler.draw();
  }

  if(numberOfSample > 0){
  
  println (frameCount%numberOfSample+1 + " " + movementInterpolated);
  }
}

void mousePressed() {
  bRecording = true;   // draw circle
  mouseRecorded = true;
  measure=0;
}
  
void activeSampling() { 
  if (measure==0 && actualSec!=lastSec && mouseRecorded == true) {
     textSize(100);
    
     fill (0, 255, 0);
     text (measure, 200, 100 );
  sampler.beginRecording();
  }
}

void stopSampling() { 
  if (measure==2 && actualSec!=lastSec) {  
     textSize(100);
   
     fill (255, 0, 0); 
       text (measure, 200, 100 );
  mouseRecorded = false;
     //**REPEAT
  bRecording = false;
  sampler.beginPlaying();
  }
}



#118134 Interpolation à partir d'un pseudo cercle.

Posté par bvking sur 22 mars 2023 - 01:39 dans Projets logiciels, web, ou simulations

Hello!

 

J'ai amélioré la methode pour enregistrer un mouvement circulaire

 

Mais le mouvement reproduit me fait ce genre de forme

 

 

class Sample {
int t;
float x, y;
Sample( int t, float x, float y ) {
this.t = t; this.x = x; this.y = y;
}
}

class Sampler {
 
ArrayList<Sample> samples;
ArrayList<Sample> samplesModified;
int startTime;
int playbackFrame;
 
Sampler() {
samples = new ArrayList<Sample>();
samplesModified = new ArrayList<Sample>();
startTime = 0;
}
void beginRecording() {
samples = new ArrayList<Sample>();
samplesModified = new ArrayList<Sample>();
playbackFrame = 0;
}
void addSample( float x, float y ) { // add sample when bRecording
int now = millis();
if( samples.size() == 0 ) startTime = now;
samples.add( new Sample( now - 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" );
if(samples.size() > 0){
float deltax = samples.get(0).x - samples.get(samples.size()-1).x;
float deltay = samples.get(0).y - samples.get(samples.size()-1).y;
float sumdist = 0;
 
for(int i = 0; i < samples.size() - 1; i++) {
sumdist += sqrt((samples.get(i).x - samples.get(i +1 ).x)*(samples.get(i).x - samples.get(i +1 ).x) + (samples.get(i).y - samples.get(i +1 ).y)*(samples.get(i).y - samples.get(i +1 ).y));
}
 
samplesModified.add( new Sample(samples.get(0).t, samples.get(0).x , samples.get(0).y ) );
float dist = 0;
for(int i = 0; i < samples.size() - 1; i++) {
dist += sqrt((samples.get(i).x - samples.get(i +1 ).x)*(samples.get(i).x - samples.get(i +1 ).x) + (samples.get(i).y - samples.get(i +1 ).y)*(samples.get(i).y - samples.get(i +1 ).y));
samplesModified.add( new Sample(samples.get(i+1).t, (int) (samples.get(i +1).x + (dist * deltax) / sumdist), (int) (samples.get(i+1).y +( dist * deltay )/ sumdist)) );
print(samples.get(i).x);
print(",");
print(samples.get(i).y);
print(",");
print( " good data x " + samplesModified.get(i).x);
print(",");
print( " good data y " + samplesModified.get(i).y);
println("");
}
}
}
 
 
void draw() {
stroke( 255 );
 
//**RECORD
beginShape(LINES);
for( int i=1; i<samples.size(); i++) {
vertex( samplesModified.get(i-1).x, samplesModified.get(i-1).y ); // replace vertex with Pvector
vertex( samplesModified.get(i).x, samplesModified.get(i).y );
}
endShape();
//**ENDRECORD
 
//**REPEAT
int now = (millis() - startTime) % fullTime();
if( now < samplesModified.get( playbackFrame ).t ) playbackFrame = 0;
while( samplesModified.get( playbackFrame+1).t < now )
playbackFrame = (playbackFrame+1) % (samples.size()-1);
Sample s0 = samplesModified.get( playbackFrame );
Sample s1 = samplesModified.get( playbackFrame+1 );
float t0 = s0.t;
float t1 = s1.t;
float dt = (now - t0) / (t1 - t0);

float x =constrain (lerp( s0.x, s1.x, dt ),-300, 300);
float y =constrain (lerp( s0.y, s1.y, dt ),-300, 300);


circle( x, y, 20 );
 
textSize (50);
 
movementInterpolated = y ;
text (" x " + x + " y " + y + " mov " + movementInterpolated , 100, 300);

}
}

Sampler sampler;


 

Image(s) jointe(s)

  • Capture d’écran 2023-03-22 à 16.11.30.png



#118073 Interpolation à partir d'un pseudo cercle.

Posté par bvking sur 18 mars 2023 - 08:48 dans Projets logiciels, web, ou simulations

Yep!

 

La v2 a l'air carrément mieux. Je dis à l'air, car il faut que je regarde dans la pratique. 

Je te dis çà demain.

Tres bonne soirée, et grrRRAAAAANNNNNNDDDDDDD merci!




#118063 Interpolation à partir d'un pseudo cercle.

Posté par bvking sur 18 mars 2023 - 04:21 dans Projets logiciels, web, ou simulations

Yep!

 

Voilà le code qui reçoit les positions des 6 encodeurs.

J'ajouterai la fonction qui contrôle les 6 moteurs si tu veux.

Merci encore. 

import processing.serial.*;
Serial encoderReceiveUSBport101; // serial port receiving datas of positions of 6 motors
Serial teensyport; // serial port sending positions to 6 motors

int actualSec,lastSec,measure,measureToStartRecording;;
boolean bRecording = false;
boolean mouseRecorded =  true;

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>();
    playbackFrame = 0;
  }
  void addSample( int x, int y ) {  // add sample when bRecording
    int now = millis();
    if( samples.size() == 0 ) startTime = now;
    samples.add( new Sample( now - 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() {
    stroke( 255 );
    
    //**RECORD
    beginShape(LINES);
    for( int i=1; i<samples.size(); i++) {
      vertex( samples.get(i-1).x, samples.get(i-1).y ); // replace vertex with Pvector
      vertex( samples.get(i).x, samples.get(i).y );
    }
    endShape();
    //**ENDRECORD
    
    //**REPEAT
    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 );
  frameRate(30); // when size is set as P3D (3 dimension) we have 27 or 28 frame (loop) per seconde
  sampler = new Sampler();
  
  //********Sending and Receiving data with two different serialport
  String[] ports = Serial.list();
  printArray(Serial.list()); // display port in terminal
  //*************** TEENSY connected
   teensyport = new Serial(this, ports[0], 115200);// choose port matching to send data
  //*************** ENCODERD connected // comment below if port not connected
  //  encoderReceiveUSBport101 = new Serial(this, Serial.list()[1], 1000000);choose port matching to receive data
  //  Read bytes into a buffer until you get a linefeed (ASCII 10):
  //  encoderReceiveUSBport101.bufferUntil('\n');
}

void draw() {
  background( 0 );
  activeSampling();
  stopSampling();
  
  if  (actualSec!=lastSec){
       lastSec=actualSec;
       measure++;
       textSize (100);
       text (measure, 100, 100 );
     }
       actualSec =(int) (millis()*0.001);  // 
 
  if( bRecording) { // draw circle
    circle( mouseX, mouseY, 10 );
    sampler.addSample( mouseX, mouseY );
  }
  
  else {    
  if( sampler.fullTime() > 0 )
        sampler.draw();
  }
}

void mousePressed() {
  bRecording = true;   // draw circle
  mouseRecorded = true;
  measure=0;
}
  
void activeSampling() { 
   if (measure<=1 && measure>=1 &&actualSec!=lastSec && mouseRecorded == true) {
  sampler.beginRecording();
  }
}

void stopSampling() { 
   if (measure<=3 && measure>=3  && actualSec!=lastSec) {  
  mouseRecorded = false;
     //**REPEAT
  bRecording = false;
  sampler.beginPlaying();
  }
}

void serialEvent(Serial encoderReceiveUSBport101) { // receive 6 datas from serialport splited with , and a last is send with println

  // read the serial buffer:
  String myString = encoderReceiveUSBport101.readStringUntil('\n');

  // if you got any bytes other than the linefeed:
  myString = trim(myString);

  // split the string at the commas
  // and convert the sections into integers:
  int values[] = int(split(myString, ','));

  if (values.length > 0) {// v0 is value of the encodeur from 0 to 4000
  int v0; int v1; int v2; int v3; int v4; int v5;

    v0 = (int) map (values[0], 0, 4000, 0, 400);
    v1 = (int) map (values[0], 0, 4000, 0, 400);
    v2 = (int) map (values[0], 0, 4000, 0, 400);
    v3 = (int) map (values[0], 0, 4000, 0, 400);
    v4 = (int) map (values[0], 0, 4000, 0, 400);
    v5 = (int) map (values[0], 0, 4000, 0, 400);
           
    println (" v0 " + v0 ); println (" v1 " + v1 ); println (" v2 " + v2 ); println (" v3 " + v3 );
    println (" v4 " + v4 ); println (" v5 " + v5 );
}
}



#118058 Interpolation à partir d'un pseudo cercle.

Posté par bvking sur 17 mars 2023 - 02:48 dans Projets logiciels, web, ou simulations

Yep,

Dans l'ideal la deniere interpolation est la plus lisse et donc m'intéresse le plus.

Mais comme je suis pressé d'avoir un resultat, la solution la plus simple m'ira.

 

Le but est quand je répète le cercle, celui ci passe par un point intermédiaire pour ne pas à avoir faire une saccade trop brutale pour revenir au point d'origine.

Surtout dans un cercle de 6400 points, il faut arriver à programmer:

Que si le point part de 0 et fini à 6234 point, alors il passe par le point intermédiaire, disons 6350, et continue à aller dans le meme sens,

c'est à dire à 0, sans revenir en arrière. Alors il faudrait que le point 0 devienne 6401.

Voiloù, c'est tout pour le moment ;)

Apres faudra penser à une solution quand le cercle tracé dépasse un tour, au quel cas il faudra considerer le point le plus proche et précédent le premier point, comme dernier point. 

Puis de meme, faire en sorte que le programme continue à faire tourner le cercle toujours dans le meme sens.

Merci Mike  :yahoo:




#118050 Interpolation à partir d'un pseudo cercle.

Posté par bvking sur 14 mars 2023 - 08:33 dans Projets logiciels, web, ou simulations

Bonjour à toutes et tous!

 

Pour un projet artistique, j'echantillonne (sampling) pendant deux secondes un pseudo cercle (pas entièrement fini) tracé à la souris.

Puis cette forme se répète toute seule.

 

J'aimerai ajouter entre le dernier et le premier point tracés, un point d'interpolation qui soit à la moyenne

de la droite affine crée par le premier et le dernier.

 

Il faut essayer de tracer un cercle sur deux secondes. L'enregistrement se fait à chaque changement de seconde.

(mais on est pas censé le savoir).

 

Merci pour votre aide ;) et ce n'est que le début!

int actualSec,lastSec,measure,measureToStartRecording;;
boolean bRecording = false;
boolean mouseRecorded =  true;

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>();
    playbackFrame = 0;
  }
  void addSample( int x, int y ) {  // add sample when bRecording
    int now = millis();
    if( samples.size() == 0 ) startTime = now;
    samples.add( new Sample( now - 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() {
    stroke( 255 );
    
    //**RECORD
    beginShape(LINES);
    for( int i=1; i<samples.size(); i++) {
      vertex( samples.get(i-1).x, samples.get(i-1).y ); // replace vertex with Pvector
      vertex( samples.get(i).x, samples.get(i).y );
    }
    endShape();
    //**ENDRECORD
    
    //**REPEAT
    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 );
  frameRate( 30 );  
  sampler = new Sampler();
}

void draw() {
  background( 0 );
  activeSampling();
  stopSampling();
  
  if  (actualSec!=lastSec){
       lastSec=actualSec;
       measure++;
       textSize (100);
       text (measure, 100, 100 );
     }
       actualSec =(int) (millis()*0.001);  // 
 
  if( bRecording) { // draw circle
    circle( mouseX, mouseY, 10 );
    sampler.addSample( mouseX, mouseY );
  }
  
  else {    
  if( sampler.fullTime() > 0 )
        sampler.draw();
  }
}

void mousePressed() {
  bRecording = true;   // draw circle
  mouseRecorded = true;
  measure=0;
}
  
void activeSampling() { 
   if (measure<=1 && measure>=1 &&actualSec!=lastSec && mouseRecorded == true) {
  sampler.beginRecording();
  }
}

void stopSampling() { 
   if (measure<=3 && measure>=3  && actualSec!=lastSec) {  
  mouseRecorded = false;
     //**REPEAT
  bRecording = false;
  sampler.beginPlaying();
  }
}

Image(s) jointe(s)

  • Capture d’écran 2023-03-14 à 20.28.39.png



#117025 Ajouter un signal circulaire à un signal circulaire. Essayer de compter les t...

Posté par bvking sur 19 octobre 2022 - 04:15 dans Programmation

Hello. Merci de te pencher sur mon prob.

 

La position absolue de chaque balle que j'utilise pour les moteurs est positionToMotor[i]

 

J'utilise newPosF[I] avec oldPosF[I] pour faire un "compteur" . C'est pour ça que je fais newPosF[i]=positionToMotor[i]%6400;

 

J'ai simplié le programme:

 

Quand t'appuies sur b t'as que le signal1 (appelé lfoPhase[1]) 

Quand t'appuies sur q t'as le signal2 + le signal1 avec le signal 2 qui s'additionne au signal1 et se "propage" sur chaque balle toutes les 200 ms.

Quand tu re appuies sur b tu vois seulement le signal1 qui se propage sur chaque balle toutes les 200 ms.

si tu re appuies sur q tu re additionne les deux signaux.

 

Si tu regardes les données de la positionMoteur i=11 (la derniere balle, celle du devant), celles si reculent puis avancent, c'est pour ça que le compteur deconne. 

import peasy.*;
PeasyCam cam;

// change these for screen size
float w = 600;
float h = 600;

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

int nbBall = 10;
//******************         FollowMovement
int formerDecayTime, decayTime;
int networkSize = 12;
int NumberofStep = 6400;
int formerFormerKey;
int formerKey;

float [] phaseFollowLFO= new float[networkSize]; // 
float [] oldPosF= new float[networkSize]; // 
float [] newPosF= new float[networkSize]; //
int [] oldPositionToMotor= new int[networkSize]; //
int [] positionToMotor=  new int [networkSize]; //
float [] oldLfoPhase=  new float[networkSize]; //
float [] lfoPhase=  new float[networkSize]; //
float [] LFO=  new float[networkSize]; //
int []  dataMappedForMotor = new int[networkSize ];
//float [] phaseShiftingFollowLFO = new float[12];
float phaseShiftingFollowLFO;
float timeLfo;
int decayTimeLfo;
int formerDecayTimeLfo;
int [] rev = new int[networkSize]; // counter of revolution
int [] revLfo = new int[networkSize]; // counter of revolution

float [] newPosX =  new float[networkSize]; //;
float [] oldPosX =  new float[networkSize]; //;

char letter;
boolean doA,doQ;
int oscillatorChange;

int decayTimeBis;
int formerDecayTimeBis;
int formerKeyMetro;

float x,y,displacement,side;

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

void setup(){
 new PeasyCam(this, 2000);
 frameRate(30); 
 formerFormerKey='#';
 key='q';
}

void draw() {
  background (0);
  
  lfoPattern();
   if (key=='b' || key=='c') {
     formerKeyMetro =  key; // choose mode to "follow"  
     }
     
  addSignal(); 
 
 //println(" formerFormerKey " + char (formerFormerKey) + " formerKey " + char (formerKey) + " key " + key)  ;
 formerFormerKey= formerKey;
 formerKey=key;
}  

void  splitTimeLfo() { 
    
  if (formerDecayTimeLfo>decayTimeLfo){
     oscillatorChange=oscillatorChange+1;
    // key='q';
  } 
  formerDecayTimeLfo = decayTimeLfo; 

   int splitTimeLfo = millis()%200; // linear time  to change " oscillator " each 200 ms
   
         oscillatorChange=oscillatorChange%12;
     if (oscillatorChange<=0) {
         oscillatorChange=2;
         }
         decayTimeLfo = splitTimeLfo;
    //     print (" oscillatorChange "); println ( oscillatorChange ); 
      
}

void lfoPattern() {
    lfoPhase[1] = PI + (frameCount / 10.0) * cos (1000 / 500.0)*-1;
    lfoPhase[2] = PI + (frameCount / 5.0) * cos (1000 / 500.0)*-1;

  }

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

void addSignal(){
  
   if (formerKeyMetro == 'b' ){
    splitTimeLfo();
    
   if (key=='q' || key=='b') {
     letter = key;   
     }
  switch(letter) {
    case 'q': 
    doQ=true;
    break;
    case 'b': 
    doQ=false;
    break;     
    }
  
   if (formerFormerKey == '#') { //  && doA==true
  //    print ("  normal " + frameCount + " lfoPhase[1] " + lfoPhase[1] + " lfoPhase[2] " + lfoPhase[2]);    println (   ); 
      for (int i = 2; i <  networkSize-0; i+=1) { 
       LFO[i] = lfoPhase[1]; 
   if (LFO[i]<0){        
       LFO[i] = phaseFollowLFO[i] -  LFO[i];
       dataMappedForMotor[i]= int (map (LFO[i], 0, -TWO_PI, NumberofStep, 0)); 

       newPosX[i]= map (dataMappedForMotor[i], NumberofStep, 0, 0, -TWO_PI);
  }
       
   else
       LFO[i] = phaseFollowLFO[i] +  LFO[i];
       dataMappedForMotor[i]= (int) map (LFO[i], 0, TWO_PI, 0, NumberofStep);

       newPosX[i]= map (dataMappedForMotor[i], 0, NumberofStep, 0, TWO_PI);
 
   }
  
   if (LFO[oscillatorChange]<0){        
       LFO[oscillatorChange] = phaseFollowLFO[oscillatorChange]-LFO[oscillatorChange]; 
       dataMappedForMotor[oscillatorChange]= int (map (LFO[oscillatorChange], 0, -TWO_PI, NumberofStep, 0)); 

       newPosX[oscillatorChange]= map (dataMappedForMotor[oscillatorChange], NumberofStep, 0, 0, -TWO_PI);
  }
       
   else
       LFO[oscillatorChange] = phaseFollowLFO[oscillatorChange]+LFO[oscillatorChange];
       dataMappedForMotor[oscillatorChange]= (int) map (LFO[oscillatorChange], 0, TWO_PI, 0, NumberofStep);

       newPosX[oscillatorChange]= map (dataMappedForMotor[oscillatorChange], 0, NumberofStep, 0, TWO_PI);
  }
 
   if (doQ==true ){
  //   pendularPattern(); // offset with lfo oscillator by osillator
    print ("  case q phaseFollowLFO " + oscillatorChange + " "  + phaseFollowLFO[oscillatorChange] + " "); print ("  LFOoscillatorChange  "); print (oscillatorChange); print ("   ") ;  print (LFO[oscillatorChange]  ); 
    print (" newPosX[oscillatorChange] " + newPosX[oscillatorChange]);
    for (int i = 2; i <  networkSize-0; i+=1) { 
   //  phaseFollowLFO[oscillatorChange]= PI/10*-oscillatorChange; // to understand
     phaseFollowLFO[oscillatorChange]= lfoPhase[2];
     LFO[oscillatorChange]=  LFO[i]+phaseFollowLFO[i];  // add offset given by pendularPattern
     LFO[oscillatorChange]=  LFO[i]; 
  
   
    if (LFO[i]<0){
   
     dataMappedForMotor[i]= int (map (LFO[i], 0, -TWO_PI, NumberofStep, 0)); 

       newPosX[oscillatorChange]= map (dataMappedForMotor[i], NumberofStep, 0, 0, -TWO_PI);
  //   newPosX[i]= LFO[i];
       }
       
   else
    
    dataMappedForMotor[i]= (int) map (LFO[i], 0, TWO_PI, 0, NumberofStep);  
    
    newPosX[oscillatorChange]= map (dataMappedForMotor[i], 0, NumberofStep, 0, TWO_PI);
    
     } //
 
   }
    print ("  LFO+LFOoscillatorChange  "); print (oscillatorChange); print ("   ") ;  println (LFO[oscillatorChange]  ); 
   
  key='#';// 

     for (int i = 2; i <  networkSize-0; i+=1) { // la premiere celle du fond i=2,  la derniere celle du devant i=11
    drawBall(i, newPosX[i] );

   
     print( " oldPositionToMotor[i]" ); print ( oldPositionToMotor[i]);
    positionToMotor[i]= (int) map (newPosX[i], 0, TWO_PI, 0, NumberofStep); //
    newPosF[i]=positionToMotor[i]%6400;
    if ( oldPosF[i]>newPosF[i]){
      revLfo[i]++;
     
    } 
     oldPositionToMotor[i]=  positionToMotor[i];
     oldPosF[i]=newPosF[i];

     print( " positionToMotor[i]" ); print ( positionToMotor[i]);
     print (" revolutionLFO "); print ( i); print ("  "); println (revLfo[i]); 
  }
  } 
}



#117019 Suivre un signal avec un décalage en temps et non en frame.

Posté par bvking sur 18 octobre 2022 - 11:39 dans Programmation

Hello Ludo.

Là on voit un signal circulaire sur 10 balles . Le signal depend de la vitesse d'incrementation de frameCount.

Le décalage entre chaque balle qui se suivent est de d*20 ms. En appuyant sur la flèche droite

String debug ="";
String dataToControlMotor;
boolean way;

// 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 nbBall = 9;
int nbMaxDelais = 2000;
float pendulairePhase;
float formerDecayTime, decayTime;
int frameCountBis = 0;
int lastSec, sec, countSec;

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

float [][] phases = new float[nbBall][nbMaxDelais];
int[] phaseToMotor;
float [] phaseMapped;

float x, y;

float Phase;

int d, k; // to modulate parameter of phase and time offset

int frameRatio;

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

void setup() {
  new PeasyCam(this, 2000);
  frameRatio=30;
  countSec=0;
  k=1;
  

  frameRate(frameRatio);
  for (int i = 0; i < nbBall; i++) {
    phaseToMotor= new int [nbBall];
    phaseMapped= new float [nbBall];

    for (int j = 0; j < nbMaxDelais; j++)
      phases[i][j] = PI;
  }
}

void draw() {
  background(0);
  if (lastSec>=sec){
  background (100);
  countSec++;
  };
  
  if (formerDecayTime>=decayTime){
      frameCountBis=frameCountBis+1;
  } 
   
   formerDecayTime = decayTime;
   decayTime = millis()%50;// counter actualise 20 times in on sec
 
    
  println( " decayT "  + decayTime + " : decay en ms " + d*50)   ;
 
  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

  if (!firstFollowingStarted) {
 
       float signal = PI + (frameCount /4) * cos (1000 / 25.0);
 
    phases[0][frameCountBis/1 % nbMaxDelais]=signal;
 
  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, d, k*QUARTER_PI/8);  // ici, le temps que les points attendent pour se suivre est de d frames (, et il faut un espace entre eux de QUARTER_PI/8

    //*****   drawBall(i, phaseMapped[i] );
    drawBall(i, phases[i][frameCountBis*1 % nbMaxDelais] );

  }   
  }  
}

void drawBall(int n, float phase) {
  pushMatrix();
  translate(-w2, -h2, -1000);
  noStroke();
  float side = height*0.15*1/nbBall;
  float rayon = width/2;
  
  x = rayon*cos(phase); //-300 à 300
  y = rayon*sin(phase);
  
  translate (x, y, 200+(50*5*n)); // 
  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 = frameCountBis % nbMaxDelais;
  int followedStep = (step + nbMaxDelais - delais) % nbMaxDelais;
  phases[follower][step] = phases[target][followedStep] + deltaphase;
}

void keyPressed () {
   
  if (keyCode == RIGHT) {
       println(" right INCREASE timeOffset ")  ; //
       d+= 1; // incremente 50 ms. So if d=10 second ball follows first with a time offset of 500 ms
       d=d%51;
       print ("d= timeOffsetRatio: ");
       println (d);
  }

  if (keyCode == LEFT) {
      println(" left INCREASE phase shifting"); //
      d-=1; // incremente de demi sec
     }
  }



#117015 Ajouter un signal circulaire à un signal circulaire. Essayer de compter les t...

Posté par bvking sur 17 octobre 2022 - 10:54 dans Programmation

Yep! c'est mieux sans les modulos. :thank_you:  

Maintenant, j'ai bien mes positions absolues sauf pour ma dernière balle où il y a des sauts sur 3 frames.

Je pense que le problème est quand j'additionne les deux signaux mais je vois pas où? 

j'ai retiré le compteur, j'en ai fait un autre, ca à l'air de fonctionner mais j'ai un problème avec la dernier balle.

 

si t'as des idées stp.... le programme est bien allégé est plus explicite je pense.

import peasy.*;
PeasyCam cam;

// change these for screen size
float w = 600;
float h = 600;

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

int nbBall = 10;
//******************         FollowMovement
int formerDecayTime, decayTime;
int networkSize = 12;
int NumberofStep = 6400;
int formerFormerKey;
int formerKey;

float [] phaseFollowLFO= new float[networkSize]; // 
float [] oldPosF= new float[networkSize]; // 
float [] newPosF= new float[networkSize]; //
int [] oldPositionToMotor= new int[networkSize]; //
int [] positionToMotor=  new int [networkSize]; //
float [] oldLfoPhase=  new float[networkSize]; //
float [] lfoPhase=  new float[networkSize]; //
float [] LFO=  new float[networkSize]; //
int []  dataMappedForMotor = new int[networkSize ];
//float [] phaseShiftingFollowLFO = new float[12];
float phaseShiftingFollowLFO;
float timeLfo;
int decayTimeLfo;
int formerDecayTimeLfo;
int [] rev = new int[networkSize]; // counter of revolution
int [] revLfo = new int[networkSize]; // counter of revolution

float [] newPosX =  new float[networkSize]; //;
float [] oldPosX =  new float[networkSize]; //;

char letter;
boolean doA,doQ;
int oscillatorChange;

int decayTimeBis;
int formerDecayTimeBis;
int formerKeyMetro;

float x,y,displacement,side;

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

void setup(){
 new PeasyCam(this, 2000);
 frameRate(30); 
 formerFormerKey='#';
 key='q';
}

void draw() {
  background (0);
  
  lfoPattern();
   if (key=='b' || key=='c') {
     formerKeyMetro =  key; // choose mode to "follow"  
     }
     
  addSignal (); 
 
 //println(" formerFormerKey " + char (formerFormerKey) + " formerKey " + char (formerKey) + " key " + key)  ;
 formerFormerKey= formerKey;
 formerKey=key;
}  

void  splitTimeLfo() { 
    
  if (formerDecayTimeLfo>decayTimeLfo){
     oscillatorChange=oscillatorChange+1;
    // key='q';
  } 
  formerDecayTimeLfo = decayTimeLfo; 

   int splitTimeLfo = millis()%200; // linear time  to change " oscillator " each 200 ms
   
         oscillatorChange=oscillatorChange%12;
     if (oscillatorChange<=0) {
         oscillatorChange=2;
         }
         decayTimeLfo = splitTimeLfo;
    //     print (" oscillatorChange "); println ( oscillatorChange ); 
      
}

void lfoPattern() {
    float signal1 = PI + (frameCount / 10.0) * cos (1000 / 500.0)*-1;
    float signal2 = PI + (frameCount / 13.0) * cos (1000 / 500.0)*-1;
 
    if (signal1 > 0 )
     lfoPhase[1]= signal1;  // gauche droite vers le hau.t CIRCULAR MODE usefull ?// diffAngle(angle, HALF_PI);//% TWO_PI  // position du point de depart + vitesse * phi constant  ==> ici vitesse du point phases[0] est constante
    else
     lfoPhase[1]= signal1;
    
     if (signal2 > 0 )
     lfoPhase[2]= signal2; 
    else
     lfoPhase[2]= signal2;
  }

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

void addSignal(){
  
   if (formerKeyMetro == 'b' ){
    splitTimeLfo();
    
   if (key=='q' || key=='a') {
     letter = key;   
     }
  switch(letter) {
    case 'q': 
    doA=false;
    doQ=true;
    break;
    case 'a': 
    doA=true;
    doQ=false;
    break;     
    }
  

   if (formerFormerKey == '#') { //  && doA==true
  //    print ("  normal " + frameCount + " lfoPhase[1] " + lfoPhase[1] + " lfoPhase[2] " + lfoPhase[2]);    println (   ); 
      for (int i = 2; i <  networkSize-0; i+=1) { 
       LFO[i] = lfoPhase[1]; 
   if (LFO[i]<0){        
       LFO[i] = phaseFollowLFO[i] -  LFO[i];
       dataMappedForMotor[i]= int (map (LFO[i], 0, -TWO_PI, NumberofStep, 0)); 

       newPosX[i]= map (dataMappedForMotor[i], NumberofStep, 0, 0, -TWO_PI);
  }
       
   else
       LFO[i] = phaseFollowLFO[i] +  LFO[i];
       dataMappedForMotor[i]= (int) map (LFO[i], 0, TWO_PI, 0, NumberofStep);

       newPosX[i]= map (dataMappedForMotor[i], 0, NumberofStep, 0, TWO_PI);
 
   }
  
   if (LFO[oscillatorChange]<0){        
       LFO[oscillatorChange] = phaseFollowLFO[oscillatorChange]-LFO[oscillatorChange]; 
       dataMappedForMotor[oscillatorChange]= int (map (LFO[oscillatorChange], 0, -TWO_PI, NumberofStep, 0)); 

       newPosX[oscillatorChange]= map (dataMappedForMotor[oscillatorChange], NumberofStep, 0, 0, -TWO_PI);
  }
       
   else
       LFO[oscillatorChange] = phaseFollowLFO[oscillatorChange]+LFO[oscillatorChange];
       dataMappedForMotor[oscillatorChange]= (int) map (LFO[oscillatorChange], 0, TWO_PI, 0, NumberofStep);

       newPosX[oscillatorChange]= map (dataMappedForMotor[oscillatorChange], 0, NumberofStep, 0, TWO_PI);
  }
 
   if (doQ==true ){
  //   pendularPattern(); // offset with lfo oscillator by osillator
    print ("  case q phaseFollowLFO " + oscillatorChange + " "  + phaseFollowLFO[oscillatorChange] + " "); print ("  LFOoscillatorChange  "); print (oscillatorChange); print ("   ") ;  print (LFO[oscillatorChange]  ); 
    print (" newPosX[oscillatorChange] " + newPosX[oscillatorChange]);
    for (int i = 2; i <  networkSize-0; i+=1) { 
   //  phaseFollowLFO[oscillatorChange]= PI/10*-oscillatorChange; // to understand
     phaseFollowLFO[oscillatorChange]= lfoPhase[2];
     LFO[oscillatorChange]=  LFO[i]+phaseFollowLFO[i];  // add offset given by pendularPattern
     LFO[oscillatorChange]=  LFO[i]; 
  
   
    if (LFO[i]<0){
   
     dataMappedForMotor[i]= int (map (LFO[i], 0, -TWO_PI, NumberofStep, 0)); 

       newPosX[oscillatorChange]= map (dataMappedForMotor[i], NumberofStep, 0, 0, -TWO_PI);
  //   newPosX[i]= LFO[i];
       }
       
   else
    
    dataMappedForMotor[i]= (int) map (LFO[i], 0, TWO_PI, 0, NumberofStep);  
    
    newPosX[oscillatorChange]= map (dataMappedForMotor[i], 0, NumberofStep, 0, TWO_PI);
    
     } //
 
   }
    print ("  LFO+LFOoscillatorChange  "); print (oscillatorChange); print ("   ") ;  println (LFO[oscillatorChange]  ); 
   
  key='#';// 

     for (int i = 2; i <  networkSize-0; i+=1) {
    drawBall(i, newPosX[i] );

   
     print( " oldPositionToMotor[i]" ); print ( oldPositionToMotor[i]);
    positionToMotor[i]= (int) map (newPosX[i], 0, TWO_PI, 0, NumberofStep); //
    newPosF[i]=positionToMotor[i]%6400;
 //   if (oldPositionToMotor[i]>positionToMotor[i]){
    if ( oldPosF[i]>newPosF[i]){
      revLfo[i]++;
     
    } 
     oldPositionToMotor[i]=  positionToMotor[i];
     oldPosF[i]=newPosF[i];

     print( " positionToMotor[i]" ); print ( positionToMotor[i]);
     print (" revolutionLFO "); print ( i); print ("  "); println (revLfo[i]); 
  }
  } 
  
  }



#116994 Ajouter un signal circulaire à un signal circulaire. Essayer de compter les t...

Posté par bvking sur 14 octobre 2022 - 08:14 dans Programmation

Bonjour,

10 boules tournent dans le sens des aiguilles d'une montre.En appuyant sur 'b', vous voyez un signal circulaire sur les 10 boules puis en appuyant sur 'q', vous pouvez voir un signal circulaire s'ajouter à une balle différente toutes les 200 ms.
J'essaie d'avoir la position absolue de chaque balle. Ensuite, je vais utiliser des positions pour les mettre dans un Arduino pour contrôler les moteurs
J'essaie d'obtenir le nombre de révolutions ; dans ce cas, je peux multiplier la révolution par la position pour avoir la position réelle mais ce n'est pas facile d'avoir le nombre de révolutions.
Peut-être y a-t-il une solution quelque part ? Ou utiliser les phases de chaque balle d'une autre manière ?
Merci beaucoup pour votre aide !
 
import peasy.*;
PeasyCam cam;

// change these for screen size
float w = 600;
float h = 600;

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

int nbBall = 10;
//******************         FollowMovement
int formerDecayTime, decayTime;
int networkSize = 12;
int NumberofStep = 6400;
int formerFormerKey;
int formerKey;

float [] phaseFollowLFO= new float[networkSize]; // 
float [] oldPosF= new float[networkSize]; // 
float [] newPosF= new float[networkSize]; //
float [] oldLfoPhase=  new float[networkSize]; //
float [] lfoPhase=  new float[networkSize]; //
float [] LFO=  new float[networkSize]; //
int []  DataToDueCircularVirtualPosition = new int[networkSize ];
//float [] phaseShiftingFollowLFO = new float[12];
float phaseShiftingFollowLFO;
float timeLfo;
int decayTimeLfo;
int formerDecayTimeLfo;
int [] rev = new int[networkSize]; // counter of revolution

float [] newPosX =  new float[12]; //;
float [] oldPosX =  new float[12]; //;

char letter;
boolean doA,doQ;
int oscillatorChange;

int decayTimeBis;
int formerDecayTimeBis;
int formerKeyMetro;

float x,y,displacement,side;

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

void setup(){
 new PeasyCam(this, 2000);
 frameRate(30); 
 formerFormerKey='#';
 key='q';
}

void draw() {
  background (0);
  
  lfoPattern();
   if (key=='b' || key=='c') {
     formerKeyMetro =  key; // choose mode to "follow"  
     }

  if (formerKeyMetro == 'b' ){
    splitTimeLfo();
    
   if (key=='q' || key=='a') {
     letter = key;   
     }
  switch(letter) {
    case 'q': 
    doA=false;
    doQ=true;
    break;
    case 'a': 
    doA=true;
    doQ=false;
    break;
     
    }
    
   if (formerFormerKey == '#') { //  && doA==true
    // lfoPattern();
      print ("  normal " + frameCount + " lfoPhase[1] " + lfoPhase[1] + " lfoPhase[2] " + lfoPhase[2]);    println (   ); 
      for (int i = 2; i <  networkSize-0; i+=1) { 
       LFO[i] = lfoPhase[1]%TWO_PI; 
   if (LFO[i]<0){        
       LFO[i] = phaseFollowLFO[i] -  LFO[i];
       DataToDueCircularVirtualPosition[i]= int (map (LFO[i], 0, -TWO_PI, NumberofStep, 0)); 

       newPosX[i]= map (DataToDueCircularVirtualPosition[i], NumberofStep, 0, 0, -TWO_PI);
  }
       
   else
       LFO[i] = phaseFollowLFO[i] +  LFO[i];
       DataToDueCircularVirtualPosition[i]= (int) map (LFO[i], 0, TWO_PI, 0, NumberofStep);

       newPosX[i]= map (DataToDueCircularVirtualPosition[i], 0, NumberofStep, 0, TWO_PI);
 
   }
  
   if (LFO[oscillatorChange]<0){        
       LFO[oscillatorChange] = phaseFollowLFO[oscillatorChange]-LFO[oscillatorChange]; 
       DataToDueCircularVirtualPosition[oscillatorChange]= int (map (LFO[oscillatorChange], 0, -TWO_PI, NumberofStep, 0)); 

       newPosX[oscillatorChange]= map (DataToDueCircularVirtualPosition[oscillatorChange], NumberofStep, 0, 0, -TWO_PI);
  }
       
   else
       LFO[oscillatorChange] = phaseFollowLFO[oscillatorChange]+LFO[oscillatorChange];
       DataToDueCircularVirtualPosition[oscillatorChange]= (int) map (LFO[oscillatorChange], 0, TWO_PI, 0, NumberofStep);

       newPosX[oscillatorChange]= map (DataToDueCircularVirtualPosition[oscillatorChange], 0, NumberofStep, 0, TWO_PI);
  }
 
   if (doQ==true ){
    lfoPattern();
   //   followSignalLfo(frameRatio);
  //   pendularPattern(); // offset with lfo oscillator by osillator
    print ("  q " + frameCount + " "); print ("  mov+LfoPhase  ");    println (LFO[oscillatorChange]  ); 
    for (int i = 2; i <  networkSize-0; i+=1) { 
     phaseFollowLFO[oscillatorChange]= PI/10*-oscillatorChange; // to understand
  //   phaseFollowLFO[oscillatorChange]= lfoPhase[1];
     LFO[oscillatorChange]=  LFO[i]+phaseFollowLFO[i];  // add offset given by pendularPattern
     LFO[oscillatorChange]=  LFO[i]%TWO_PI; 
  
   
    if (LFO[i]<0){
   
     DataToDueCircularVirtualPosition[i]= int (map (LFO[i], 0, -TWO_PI, NumberofStep, 0)); 
      

       newPosX[oscillatorChange]= map (DataToDueCircularVirtualPosition[i], NumberofStep, 0, 0, -TWO_PI);
  //   newPosX[i]= LFO[i];
       }
       
   else
    
    DataToDueCircularVirtualPosition[i]= (int) map (LFO[i], 0, TWO_PI, 0, NumberofStep);  
    
    newPosX[oscillatorChange]= map (DataToDueCircularVirtualPosition[i], 0, NumberofStep, 0, TWO_PI);
    
     } //
 
   }
  //   doQ=false;
  key='#';// key='a'; // formerFormerKey = '#';

     for (int i = 2; i <  networkSize-0; i+=1) {
    drawBall(i, newPosX[i] );
    println ("  newPosX[i]" +    newPosX[i]  ); 
  }
   countRevsCaseB();
    for (int i = 2; i <  networkSize-0; i+=1) {
 
    oldPosX[i]=   newPosX[i] ; 
  }
  } 
 println(" formerFormerKey " + char (formerFormerKey) + " formerKey " + char (formerKey) + " key " + key)  ;
 formerFormerKey= formerKey;
 formerKey=key;
}  

void countRevsCaseB() { // ============================================= Ter NE PAS TOUCHER LE COMPTEUR ou Reduire l'espace avant et apres 0 pour eviter bug à grande vitesse
  
  for (int i = 0; i <  networkSize; i++) { 
    // decrement caused by negative angular velocity
    // both positive angles || both negative angles || positive-to-negative angle
    //   if (//(net.oldPhase[i] < 0.25 * PI && net.phase[i] > 1.75 * PI) ||//
    if (
      ((oldPosX[i] < 0.25 *PI && oldPosX[i]>0)  && (newPosX[i] > -0.25* PI && newPosX[i] <0))  || 
      (oldPosX[i] < -1.75 * PI && newPosX[i] > -0.25 * PI)// ||
      ) {

      rev[i]--;
 
    } else { // if you do twice there is a funny bug
      //    decompte[i]  ++; 
      //   revolution[i]=0;
    }
    // increment caused by positive angular velocity
    // both positive angles || both negative angles || negative-to-positive angle

    if (
      ((oldPosX[i] > -0.25 *PI && oldPosX[i]<0)  && (newPosX[i] < 0.25* PI && newPosX[i] >0))  || 
      (oldPosX[i] > 1.75 * PI && newPosX[i] < 0.25*PI)
      ) {
      rev[i]++;
    } else {

    }
      print (" revolution "); print ( i); print ("  "); println (rev[i]);
  }
 
 } 
 
void  splitTimeLfo() { 
    
  if (formerDecayTimeLfo>decayTimeLfo){
  oscillatorChange=oscillatorChange+1;
 // key='q';
  } 
  formerDecayTimeLfo = decayTimeLfo; 

   int splitTimeLfo = millis()%200; // linear time  to change " oscillator " each 200 ms
   
         oscillatorChange=oscillatorChange%12;
     if (oscillatorChange<=0) {
         oscillatorChange=2;
         }
         decayTimeLfo = splitTimeLfo;
         print (" oscillatorChange "); println ( oscillatorChange ); 
      
}

void lfoPattern() {
    float signal1 = PI + (frameCount / 10.0) * cos (1000 / 500.0)*-1;
    float signal2 = PI + (frameCount / 11.0) * cos (1000 / 500.0)*-1;
 
    if (signal1 > 0 )
     lfoPhase[1]= signal1%TWO_PI;  // gauche droite vers le hau.t CIRCULAR MODE usefull ?// diffAngle(angle, HALF_PI);//% TWO_PI  // position du point de depart + vitesse * phi constant  ==> ici vitesse du point phases[0] est constante
    else
     lfoPhase[1]= signal1%TWO_PI;
    
     if (signal2 > 0 )
     lfoPhase[2]= signal2%TWO_PI;  // gauche droite vers le hau.t CIRCULAR MODE usefull ?// diffAngle(angle, HALF_PI);//% TWO_PI  // position du point de depart + vitesse * phi constant  ==> ici vitesse du point phases[0] est constante
    else
     lfoPhase[2]= signal2%TWO_PI;
     
  //  print (" lfoPhase[1] "); print (lfoPhase[1]);   print (" lfoPhase[2] "); println (lfoPhase[2]);
    
  }

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

 




#116631 Suivre un signal avec un décalage en temps et non en frame.

Posté par bvking sur 12 septembre 2022 - 11:34 dans Programmation

Bonjour,

 

Une balle [0] oscillant entre 0 et PI est suivie par 9 autres balles sans décalages temporels. Elles ont donc le meme signal.

J'aimerais, en appuyant une fois sur la flèche droite, que les balles de 1 à 9 autres suivent la balle 0 avec 1 à 9 * 500 ms seconde de retard.

J'ai un premier  programme qui fonctionne, les balles suivent bien le signal avec 10, 20 ... frame de retard.

Mais je veux qu'elles suivent le signal en fonction de l'incrementation d'un temps et non par l'incrementation par image ( par la fonction frameCount qui s'actualise dans la main loop).

Comment puis je faire?

J'ai fait une variable qui s'actualise avec la fonction millis() qui s'actualise bien avec l'horloge du processeurs et non par frameCount.

Ca fonctionne, mais mon incrementation temporelle n'est pas precise.

Aussi, je n'arrive pas à récupérer les positions des balles qui suivent la balle 0.

 

Merci pour vos signaux éclairés!

 

PS: Ici est le programme où frameCount est remplacé par frameCountBis qui s'actualise avec millis() 

String debug ="";
String dataToControlMotor;
boolean way;

// 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 nbBall = 9;
int nbMaxDelais = 2000;
float pendulairePhase;
float formerDecayTime, decayTime;
int frameCountBis = 0;
int lastSec, sec, countSec;

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

float [][] phases = new float[nbBall][nbMaxDelais];
int[] phaseToMotor;
float [] phaseMapped;

float x, y;

float Phase;

int d, k; // to modulate parameter of phase and time offset

int frameRatio;

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

void setup() {
  new PeasyCam(this, 2000);
  frameRatio=30;
  countSec=0;
  k=1;
  

  frameRate(frameRatio);
  for (int i = 0; i < nbBall; i++) {
    phaseToMotor= new int [nbBall];
    phaseMapped= new float [nbBall];

    for (int j = 0; j < nbMaxDelais; j++)
      phases[i][j] = PI;
  }
}

void draw() {
  background(0);
  if (lastSec>=sec){
  background (100);
  countSec++;
  };
  
  if (formerDecayTime>=decayTime){
      frameCountBis=frameCountBis+1;
  } 
   
   formerDecayTime = decayTime;
   decayTime = (millis()*1)%20;// counter actualise 20 times in on sec
   lastSec= sec; 
   sec=millis()%1000;
    
  println(frameCount + ": " + frameRatio + " : incrementTime " + frameCountBis + " Sec " + second() + " : sec " + countSec  + " decayT "  + decayTime + " : decay en ms " + d*50)   ;
 
  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

  if (!firstFollowingStarted) {
    float signal = diffAngle(PI + (frameCountBis /4) * cos (1000 / 250.0), 0);

    print ("signal ");
    print ( signal );
    
    float deltaFollow = PI/180;
     
  if (signal > 0 )
      phases[0][frameCountBis/1 % nbMaxDelais]= diffAngle(signal, HALF_PI);//% 
  else
      phases[0][frameCountBis/1 % nbMaxDelais]= diffAngle(2* PI, signal + HALF_PI);//% TWO_PI
      drawBall(0, phases[0][frameCountBis  % 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, d, k*QUARTER_PI/8);  // ici, le temps que les points attendent pour se suivre est de d frames, et il faut un espace entre eux de QUARTER_PI/8

    //*****   drawBall(i, phaseMapped[i] );
    drawBall(i, phases[i][frameCountBis*1 % nbMaxDelais] );

  }   
      float balle0;
      float balle1;
      float balle2;
      
  balle0 = phases[0][frameCountBis  % nbMaxDelais];
  balle1 = phases[1][frameCountBis  % nbMaxDelais];
  balle2 = phases[2][frameCountBis  % nbMaxDelais];
  
    println(" balle0 " + balle0 + " balle1 " + balle1 + " balle2 " + balle2)  ;


}

void drawBall(int n, float phase) {
  pushMatrix();
  translate(-w2, -h2, -1000);
  noStroke();
  float side = height*0.15*1/nbBall;
  float rayon = width/2;
  
  x = rayon*cos(phase); //-300 à 300
  y = rayon*sin(phase);
  
  translate (x, y, 200+(50*5*n)); // 
  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 = frameCountBis % 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;
}

void keyPressed () {
   
  if (keyCode == UP) {
    frameRatio=frameRatio+5;
    frameRatio=frameRatio%65;
 
      if (frameRatio <=0 ){
       frameRatio=5;
      }
       frameRate(frameRatio);  
  }
  if (keyCode == DOWN) {
   
  if (frameRatio <=5 ){
       frameRatio=5;
      }
       frameRatio=frameRatio-1;
  }
       frameRate(frameRatio); // pas dans le void draw
  
  if (keyCode == RIGHT) {
       println(" right INCREASE timeOffset ")  ; //
       d+= 10; // incremente de demi sec. I need to increment 1282 to have 60 sec. So one sec is 1282/60 => 21.5 incrementations/sec
       d=d%65;
       print ("d= timeOffsetRatio: ");
       println (d);
  }

  if (keyCode == LEFT) {
      println(" left INCREASE phase shifting"); //
      d-=10; // incremente de demi sec
     }
  }

programme avec FrameCount

String debug ="";
String dataToControlMotor;
boolean way;

// 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 nbBall = 9;
int nbMaxDelais = 2000;
float pendulairePhase;
float formerDecayTime, decayTime;
int frameCountBis = 0;
int lastSec, sec, countSec;

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

float [][] phases = new float[nbBall][nbMaxDelais];
int[] phaseToMotor;
float [] phaseMapped;

float x, y;

float Phase;

int d, k; // to modulate parameter of phase and time offset

int frameRatio;

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

void setup() {
  new PeasyCam(this, 2000);
  frameRatio=30;
  countSec=0;
  k=1;
  

  frameRate(frameRatio);
  for (int i = 0; i < nbBall; i++) {
    phaseToMotor= new int [nbBall];
    phaseMapped= new float [nbBall];

    for (int j = 0; j < nbMaxDelais; j++)
      phases[i][j] = PI;
  }
}

void draw() {
  background(0);
  if (lastSec>=sec){
  background (100);
  countSec++;
  };
  
  if (formerDecayTime>=decayTime){
      frameCountBis=frameCountBis+1;
  } 
   
   formerDecayTime = decayTime;
   decayTime = (millis()*1)%20;// counter actualise 20 times in on sec
   lastSec= sec; 
   sec=millis()%1000;
    
  println(frameCount + ": " + frameRatio + " : incrementTime " + frameCountBis + " Sec " + second() + " : sec " + countSec  + " decayT "  + decayTime + " : decay en ms " + d*50)   ;
 
  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

  if (!firstFollowingStarted) {
    float signal = diffAngle(PI + (frameCount /4) * cos (1000 / 250.0), 0);

    print ("signal ");
    print ( signal );
    
    float deltaFollow = PI/180;
     
  if (signal > 0 )
      phases[0][frameCount/1 % nbMaxDelais]= diffAngle(signal, HALF_PI);//% 
  else
      phases[0][frameCount/1 % nbMaxDelais]= diffAngle(2* PI, signal + HALF_PI);//% TWO_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, d, k*QUARTER_PI/8);  // ici, le temps que les points attendent pour se suivre est de d frames, et il faut un espace entre eux de QUARTER_PI/8

    //*****   drawBall(i, phaseMapped[i] );
    drawBall(i, phases[i][frameCount*1 % nbMaxDelais] );

  }   
      float balle0;
      float balle1;
      float balle2;
      
  balle0 = phases[0][frameCount  % nbMaxDelais];
  balle1 = phases[1][frameCount  % nbMaxDelais];
  balle2 = phases[2][frameCount  % nbMaxDelais];
  
    println(" balle0 " + balle0 + " balle1 " + balle1 + " balle2 " + balle2)  ;
}

void drawBall(int n, float phase) {
  pushMatrix();
  translate(-w2, -h2, -1000);
  noStroke();
  float side = height*0.15*1/nbBall;
  float rayon = width/2;
  
  x = rayon*cos(phase); //-300 à 300
  y = rayon*sin(phase);
  
  translate (x, y, 200+(50*5*n)); // 
  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;
}

void keyPressed () {
   
  if (keyCode == UP) {
    frameRatio=frameRatio+5;
    frameRatio=frameRatio%65;
 
      if (frameRatio <=0 ){
       frameRatio=5;
      }
       frameRate(frameRatio);  
  }
  if (keyCode == DOWN) {
   
  if (frameRatio <=5 ){
       frameRatio=5;
      }
       frameRatio=frameRatio-1;
  }
       frameRate(frameRatio); // pas dans le void draw
  
  if (keyCode == RIGHT) {
       println(" right INCREASE timeOffset ")  ; //
       d+= 10; // incremente de demi sec. I need to increment 1282 to have 60 sec. So one sec is 1282/60 => 21.5 incrementations/sec
       d=d%65;
       print ("d= timeOffsetRatio: ");
       println (d);
  }

  if (keyCode == LEFT) {
      println(" left INCREASE phase shifting"); //
      d-=10; // incremente de demi sec
     }
  }



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

Posté par bvking sur 20 août 2022 - 07:18 dans Programmation

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();

}



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

Posté par bvking sur 20 août 2022 - 12:37 dans Programmation

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;
   }   
} 



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

Posté par bvking sur 17 août 2022 - 05:44 dans Programmation

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;
   }   
}



#115794 Bien paramétrer un mouvement simple et le complexifier.

Posté par bvking sur 27 avril 2022 - 07:37 dans Programmation

 

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:




#115708 Bien paramétrer un mouvement simple et le complexifier.

Posté par bvking sur 05 avril 2022 - 08:33 dans Programmation

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;
}



#115637 Fonction qui déclenche des événements en fonction de l'espace et du temps.

Posté par bvking sur 26 mars 2022 - 06:52 dans Programmation

Bonjour à toutes et tous.

 

Je repose cette question de programmation de manière plus explicite, dites moi si ce service nécessite une rémunération.

Voilà une petite demo pour vous montrer à quoi peut servir le programme que je mets en piece jointe

https://youtu.be/a6RVfLpc1QA

 

Ma question est enregistrée sur cette vidéo,https://youtu.be/skhBxpsSW2Y Attention à un moment je dis que le point 2 doit suivre le point 2, mais c'est le point 3 qui doit suivre le point 2. Comme toujours d'ailleurs.

 

Hello.

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.
Mon problème est que j’aimerais que le point 4 suivent le point 3 avec le meme décalage temporel et spatiale que le premier point 3 qui suit le point tournant, appelé point 2.
 
Explication de la fonction.
Pour commencer, il faut pouvoir faire en sorte qu’un point 2 se deplaçant de maniere circulaire, soit suivi par un autre point 3 se deplacant aussi de maniere de circulaire. 
A la base le point 3 n’a pas de vitesse et il est à la position 0
 
Pour ce fairre, il faut un décalage de phase entre 3 et 2 de deux manières.
une temporelle: 
 
De telle sorte que 3 ait la phase 2 avec un temps de décalage nul ou de 225 ms par exemple. 
Dans le premier cas 2 et 1 ont exactement la meme position
Dans le second on observe un retard de 225 ms. Il faut taper sur la fleche de gauche pour augmenter le temps. Sur l’écran, on voit D ratio qui augmente par pas de 75ms. 
 
une spatiale:
 
De telle sorte que 3 ait la phase 2 avec une position de décalage, cest à dire, que sil y a un ecart entre la position 1 en mouvement et la position 2 à l’arrêt, la position 2 avance par à coup, dès que la difference entre la position 3 et 2 est supérieure à , par exemple 45°, soit TWO_PI/8.
 
Dans mon programme, il faut 6400 pas pour faire un tour, donc 45 °= 6400/8= 800 points. On change l’espace de la phase avec la fleche droite; ce qui change le parametre K phi. K phi= 1==> 100 points, donc pour 45°, il faut taper sur la fleche de droite 8 fois.
 
Puis essayer de voir si on peut combiner les deux : 
 
Faire en sorte que la position 3 avance de 45° apres 225 ms à compter du moment où la difference entre la position 3 et 2 a été supérieure à 45°.
Normalement le point 3 devrait être à la position du point 2, où il se trouvait il y a 225 ms, si le point a avancé de plus de 800 points.
Pour que le point 3 suive le point 2 où il etait, j’ai rajouté une variable appelée interphase. 
 
Cest sur cette derniere partie que je sèche,le point 3 suit bien le point 2, mais je n'arrive pas à faire en sorte aue le point 4 suive le point 3 en attendant 225 ms avant de se mettre à la position du point 3,  là, où il etait il y a 225 ms. La 3 devrait suivrent la deux avec une retard de 225 ms et un ecart de 45° et ainsi de suite pour les positions i+1 et i, mais mon programe ne semble pas fonctionner.
 
J'ai pré-enregistré une sequence avec différents paramètres de décalage de phase spatiale et temporelle. 
En bas de l'écran:
K phi=0 veut dire 0 décalage de phase.  K phi=2 ==> 200 points de décalage
D ratio =225 veut dire 225 ms de décalage de phase.
 
Fonctionnement du programme avec les touches du claviers.
 
Pour basculer le mouvement des points en mode circulaire, enfoncez la touche *
Pour basculer en mode pendulaire avec $, mais vous n'aurez pas besoin de l'utiliser pour l'instant.
Réaligner les points vers le haut avec ç
Augmenter le décalage de  phase avec la flèche de gauche
Augmenter le décalage de  temporel avec la flèche de droite
Mettre le point 2 à vitesse 2 avec A
Diviser la fréquence par 2 avec n
Multiplier la fréquence par 2 avec N
Pour arrêter l'animation, touche !
Pour relancer l'animation, touche :
 
Si la fonction s'arrête, on la relance avec la touche o. On la trouve dans le programme en cherchant void formerkeyo
 
Pour ne plus avoir les pre enregistrements, il faut choisir le fichier vide, qui est placé sous le commentaire fichier vide.
 
Merci et dites moi, combien faut’il vous financer pour resoudre mes erreurs de programmation.
 
Pour ce qui sont motivé, il faudrait mieux communiquer par tel.
Mercis @ l'infini !8)

Fichier(s) joint(s)




#115587 Décaler un événement de 200ms. Pourquoi je ne peux en décaler plusieurs?

Posté par bvking sur 05 mars 2022 - 10:08 dans Projets logiciels, web, ou simulations

Bonjour à tous!

 

Pour mon installation artistique, j’aimerai à partir du mouvement d’un point tournant à vitesse constante, pouvoir faire que 9 autres points suivent le premier avec des decalages temporels et spatiaux.
Voici le lien pour voir des exemples d'utilisations avec des différents décalages temporels et spatiaux. https://youtu.be/IJ1tZstcywA
Dans la video, je commence à changer le temps en millisecondes et la phase de décalage. Mais le problème c'est que tous les points suivants se décalent instantanément, sans attendre les 2XX millisecondes.  :help:
 
Pour commencer, il faut pouvoir faire en sorte qu’un point appelé 3 se deplaçant de maniere circulaire, soit suivi par un autre point appelé 2 se deplacant aussi  de maniere de circulaire. Le point 2 à une vitesse circulaire constante
A la base le point 3 n’a pas de vitesse et il est à la position 0
 
J'arrive à gerer un décalage de phase entre 3 et 2 de deux manières.
une temporelle: 
 
De telle sorte que 3 ait la phase 2 avec un temps de décalage nul ou de 200 ms par exemple. 
Dans le premier cas, 3 et 2 ont exactement la meme position
Dans le second on observe une latence.
 
une spatiale:
 
De telle sorte que 3 ait la phase 2 avec une position de décalage, cest à dire, que sil y a un ecart entre la position 2 en mouvement et la position 3 à l’arrêt, la position 3 avance par à-coups, dès que la difference entre la position 3 et 2 est supérieure à 45° par exemple. 
 
Puis essayer de voir si on peut combiner les deux : 
 
Faire en sorte que la position 3 avance de 45° apres 200 ms à compter du moment où la difference entre la position 2 et 3 a été supérieure à 45°.
 
Cest sur cette derniere partie que je sèche, jarrive à le faire avec la position 3 et 2, mais jarrive pas à généraliser avec les positions suivantes. La 4 devrait suivre la 3 avec une retard de 200 ms et un ecart de 45° et ainsi de suite pour les positions i+1 et i. 
Espérant avoir été clair, je mets la fonction ci dessous, si vous avez des idées.
Merci pour vos efforts!   ;)
 
 
 
void formerKeyo() {
 if (circularMov==true ){   
if (d>=0){
    decay=d; // decay in millis (50,.. 1000 ms),  before changing phase i+1 with the phase from i
}   
   if (k>=0){
      phiShift=k*-PI/16; // here the position to add or substrat to the next point (i+1)
      mapShiftCircular= map (phiShift, 0, 16*-PI/16, 0, 6400);   // one revolution is 6400 step 
  //  mapShiftCircular is the space to reach in order to follow the previous point 
}
   formerEvent[2]=millis();   // time from the beginning of the launch of the program.
}

  for (int i = 2; i < (3); i++) {
      
       if ( circularMov==true  && // mapShiftCircular is the space between two points
   //points goes in clock wise
    ((CircularOldVirtualPosition[2] <= CircularVirtualPosition[2+1]+mapShiftCircular) && (CircularVirtualPosition[2] >= CircularVirtualPosition[2+1]+mapShiftCircular) &&
     (CircularOldVirtualPosition[2]+800*0.1 < CircularVirtualPosition[2]+800*0.1))
   
    ||
    ((CircularOldVirtualPosition[2]+mapShiftCircular >= CircularVirtualPosition[2+1]) && (CircularVirtualPosition[2]<= CircularVirtualPosition[2+1]+mapShiftCircular) &&
     (CircularOldVirtualPosition[2]+800*0.1 > CircularVirtualPosition[2]+800*0.1))
  //points goes in counter clock wise
    )
  
     { 
         twoTree = true;
  }
     else twoTree= false;  
   if  (//formerEvent[2]%250>200
     formerEvent[2]>formerEvent[3]+decay && twoTree== false // twoTree== true do not trig the program below
       ){
          net.phase[3]=(net.phase[2])-phiShift*1;//
          net.phase[3]= net.phase[3]%TWO_PI;//   
         memoryi=i;  
         formerEvent[3]=formerEvent[2];
       // noLoop();
          }        
   }

 for (int j = 3; j < (11); j++) {
      
       if ( circularMov==true  &&
   
    ((CircularOldVirtualPosition[j] <= CircularVirtualPosition[j+1]+mapShiftCircular) && (CircularVirtualPosition[j] >= CircularVirtualPosition[j+1]+mapShiftCircular) &&
     (CircularOldVirtualPosition[j]+800*0.1 < CircularVirtualPosition[j]+800*0.1))
   
    ||
    
    ((CircularOldVirtualPosition[j]+mapShiftCircular >= CircularVirtualPosition[j+1]) && (CircularVirtualPosition[j]<= CircularVirtualPosition[j+1]+mapShiftCircular) &&
     (CircularOldVirtualPosition[j]+800*0.1 > CircularVirtualPosition[j]+800*0.1))
  
    )
  
     { 
         followNumber[j]= true;
         formerEvent[j+0]=formerEvent[2];
  }
         else followNumber[j]= false;
     
   if  (
 //  formerEvent[2]>formerEvent[j+1]+decay && followNumber[j]==false
     formerEvent[j+0]>formerEvent[j+1]+decay && followNumber[j]==false
   ){
   
         print ("net.phase ") ;  print (j); print (" ") ; print (net.phase[j+0]) ; //  println();
         print ("net.phase ") ;  print (j+1); print (" ") ; println (net.phase[j+1]) ; //  println();
         net.phase[j]=net.phase[j]%TWO_PI;
          net.phase[j+1]=(net.phase[j])-phiShift;// 
          net.phase[j+1]= net.phase[j+1]%TWO_PI;//  keep phase between 0 and TWO_PI
    
        memoryi=j;  
        formerEvent[j+1]=formerEvent[2];  
        }       
   }
 
 

 




#114955 Fixe une roue denté autour d'un axe moteur. Sur un nema 17

Posté par bvking sur 20 décembre 2021 - 11:52 dans Mécanique

Bon, merci pour tous les conseils. Bref et précis! Bonne soirée  :thank_you:




#114953 Fixe une roue denté autour d'un axe moteur. Sur un nema 17

Posté par bvking sur 20 décembre 2021 - 10:43 dans Mécanique

sisi je ferai ca. là je suis content grace à mon réducteur, je peux porter une charge bien plus lourde. Mais le réducteur chinois est vraiment pas à la bonne mesure.

Et que le "systeme qu'on fixe sur l'axe de sortie du réducteur,a été livré sans les petites vis pour le fixer dessus. 

Donc j'ai mis des bouts de plastiques en guise de joint. Et ca fonctionne.

Comme tu peux voir j'ai un trou de 1.5 cm entre le réducteur est le nema 17.

Donc, je me demande soit je passe sur des nema 23 mais faut acheter les drivers TB6000, soit j'achète les nema 17 avec réducteur inclus.

Ces derniers valent 25 euros pieces et les nema 23 a peu près pareil si on achète au moins 3 ou 5. Et comme il m'en faut 10... 

 

Pour l'instant j'arrive à faire tourner une barre en aluminium à laquelle est fixée au bout une lumière de 140 gramme.

 

Est ce le nema 23 sont beaucoup plus puissant, car dans l'ideal, j'aimerai faire tourner une barre en aluminium de 100 g auquelle est fixé une lumière de 140 gramme, avec des acceleration de 1à 2 tours/s. 

 

ca fait beaucoup de question, sorry.

 

Si tu me dis que j'ai seulement qu'a augmenter la reduction alors ca me va aussi!

Image(s) jointe(s)

  • Photo le 20-12-2021 à 22.29.jpg