Outils pour utilisateurs

Outils du site


wiki:projets:athletagraphie:athletagraphie

Athleta'Graphie

Aire de jeu éphémère

  • Porteur du projet : Julien Stahl
  • Mail: stahl.julien@gmail.com
  • Contexte : Macro projet DSAA

Description

L’espace public urbain semble aujourd’hui majoritairement fréquenté à des fins fonctionnelles et commerciales. La multiplication des villes «connectées» nous laisse présager que la situation ne va pas changer, au contraire. En effet, les milliers de capteurs qui composent ces villes vont permettre de planifier au mieux nos déplacements, consommations, etc.

De plus, dans un contexte où la retranscription à grande échelle par les médias de certains événements ou faits sportifs met en évidence des valeurs parfois en décalage avec l’éthique initiale du sport (cf. mémoire), j’ai eu l’envie de réaliser un projet prenant le contre-pied de ces faits, prônant des valeurs citoyennes à travers le sport.

Mon intention est de réaliser un changement de fonction éphémère, facile et rapide, d’une partie d’un espace public pour en faire un lieu sportif/ludique afin de permettre aux citoyens de partager des moments de détente et de plaisir et pour favoriser le rapprochement des individus par le jeu/sport.

La solution technique qui m’est apparue comme la plus pertinente afin de respecter cette volonté d’éphémérité nécessaire au respect des usages premiers de ces lieux et afin de ne pas dégrader ces lieux communs à tous est un système de projection lumineuse qui va venir se superposer à n’importe quel sol/mur/lieu. En associant la projection à une caméra nous allons à la fois pouvoir reconstruire les conditions d’une «smart city», adapter l’aire de jeu au mieux au contexte particulier et l’utiliser pour créer des principes de jeux (ex : tracking d’une balle, détecter des zones, …).

Photographies

Vidéo

Premières expérimentations sur écran.

Prochaine étape : remplacer l'écran par un vidéo-projecteur.

Expérimentation 1

Matériel

  • Webcam
  • Vidéoprojecteur
  • Miroir ?
  • Balle (couleur vive)
  • processing
  • arduino
  • capteurs de vibrations

Code Arduino

int firstSensor = 0;    // first analog sensor
int secondSensor = 0;   // second analog sensor
int inByte = 0;         // incoming serial byte

void setup()
{
  // start serial port at 9600 bps:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  pinMode(0, INPUT);   // digital sensor is on digital pin 0
  establishContact();  // send a byte to establish contact until receiver responds 
}

void loop()
{
  // if we get a valid byte, read analog ins:
  if (Serial.available() > 0) {
    // get incoming byte:
    inByte = Serial.read();
    // read first analog input, divide by 4 to make the range 0-255:
    firstSensor = analogRead(A0);
    // delay 10ms to let the ADC recover:
    delay(10);
    // read second analog input, divide by 4 to make the range 0-255:
    secondSensor = analogRead(1); 
    // send sensor values:
    Serial.write(firstSensor);
    Serial.write(secondSensor);              
  }
}

void establishContact() {
  while (Serial.available() <= 0) {
    Serial.print('A');   // send a capital A
    delay(300);
  }
 
}

Processing

import processing.video.*;
import processing.serial.*;

Capture cam;
PGraphics img;


// variable globales liées à la communication série
Serial myPort;                       // The serial port
int[] serialInArray = new int[2];    // Where we'll put what we receive
int serialCount = 0;                 // A count of how many bytes we receive
int val;                  // Starting position of the ball
int val2;
boolean firstContact = false;        // Whether we've heard from the microcontroller

// variable globale choisie pour la couleur par défaut du traking
color selected = color(145,75,85); // couleur selectionnée
color colorSpot = color(255); // couleur du spot de traking


// variables booleenne permettant de savoir quel capteur est actionné
boolean isTouched_1=false;
boolean isTouched_2=false;


void setup() 
{
  size(640,480);       //taille de l'image
  background(255);     // couleur de fond
  smooth();
  cam = new Capture(this,640,480,"Logitech Webcam C100",30);  // définir les classes
  cam.start();                                                // commencer la capture de l'image par la webcam
  img = createGraphics(640,480,JAVA2D);                       // crée un "calque" pour dessiner sans altérer le reste de l'image 
  
 // String[] devices = Capture.list();    // liste des caméras intégrés / branchés à l'ordi
 // println(devices);                     // affichage de cette liste 
 
   printArray(Serial.list());             // affichage des ports séries
  String portName = Serial.list()[1];     // définit le port à utiliser
  myPort = new Serial(this, portName, 9600);     // définir les classes
  
}

void draw()
{
  //lancer la lecture de la vidéo
  if (cam.available()) {
    cam.read(); 
  // chargement des pixels de l vidéo  
    cam.loadPixels();
    
    // pick a different selected color, if you want
    if(mousePressed) selected = cam.pixels[mouseX+mouseY*cam.width];
    
    // search for the pixel closer to the selected color
    int sx = 0, sy = 0; // selected position
    float minDist = 10; // sensibilité de la detection de la couleur
    for(int y = 0; y < cam.height; y ++) {  
      for(int x = 0; x < cam.width; x ++) {
        color c = cam.pixels[x+y*cam.width];
        float d = dist(red(c),green(c),blue(c),
                       red(selected),green(selected),blue(selected));
        if(d < minDist) { minDist = d; sx = x; sy = y; }
      }
    }
    
    
    // test de l'état des capteurs
    if( val > 20) { // capteur 1 touché, capteur 2 desactivé
    isTouched_1 = true;
    isTouched_2 = false;
   }
  if( val2 > 20) {   // capteur 2 touché, capteur 1 desactivé
    isTouched_2 = true;
    isTouched_1 = false;
    }
    
    if(isTouched_1 == true){
      println("capteur 1: " + isTouched_1);   // verification des valeurs obtenues
      colorSpot=color(255,0,0);               // couleur de la trace
    
    }
    
    
    if(isTouched_2 == true){
      println("capteur 2: " + isTouched_2);     // verification des valeurs obtenues
      colorSpot=color(0,255,0);                 // couleur de la trace
    
    }
    
    
    /// dessin du spot
    // update the painted image
    img.beginDraw();
    img.smooth();
    //img.fill(0,255,0,100); //choisir la couleur du dessin
    img.noStroke();
    
  
    //fill(colorSpot);
    img.fill(colorSpot);
    img.ellipse(sx,sy,25,25);  // taille et position du cercle utiliser pour dessiner
    //img.strokeWeight(5);
    //img.line(sx,sy,sx++,sy++);
    img.endDraw();
    

    
    // draw the cam image and on top of that draw the painted image
    //image(cam,0,0);    //afficher la vidéo en font
    image(img,0,0);      //afficher le dessin
    //noFill(); 
    //noStroke();
    //stroke(200,255,200); 
    //strokeWeight(5);
    //ellipse(sx,sy,25,25);
  }
}

void keyPressed() {
  // réinitialiser la page
  if(key == ' ') img = createGraphics(cam.width,cam.height,JAVA2D);
}

// Connection processing/arduino
void serialEvent(Serial myPort) {
  // read a byte from the serial port:
  int inByte = myPort.read();
  // if this is the first byte received, and it's an A,
  // clear the serial buffer and note that you've
  // had first contact from the microcontroller. 
  // Otherwise, add the incoming byte to the array:
  if (firstContact == false) {
    if (inByte == 'A') { 
      myPort.clear();          // clear the serial port buffer
      firstContact = true;     // you've had first contact from the microcontroller
      myPort.write('A');       // ask for more
    } 
  } 
  else {
    // Add the latest byte from the serial port to array:
    serialInArray[serialCount] = inByte;
    serialCount++;

    // If we have 3 bytes:
    if (serialCount > 1 ) {
      val = serialInArray[0];
      val2 = serialInArray[1];
      //fgcolor = serialInArray[2];

      // print the values (for debugging purposes only):
      println(val + "\t" + val2 + "\t");

      // Send a capital A to request new sensor readings:
      myPort.write('A');
      // Reset serialCount:
      serialCount = 0;
    }
  }
}

Sketch

Schémas

Devant le manque de hauteur sous plafond pour obtenir une projection assez grande, j'ai recherché une solution pour agrandir cette image. Il est possible de gagner une distance de projection (d) à l'aide d'un miroir afin d'agrandir la longueur de la projection (L). J'ai réalisé un certains nombre de relevé à partir du projecteur qui était à ma disposition grâce auxquelles j'ai pu réaliser une courbe et ainsi pu retrouver les valeurs idéales pour avoir la projection au sol à la bonne taille.

Je souhaiterais réaliser un terrain de 300cm de longueur, si la courbe à pour équation y=2,386x-1,3946,

alors d=2,386L-1,3946,

alors pour L=300,

d=2,386*300-1,3946

d=717,41cm

Sachant que j'ai une hauteur sous plafond (h) de 224,5cm, je peux donc en déduire la distance entre le projecteur et le miroir (a):

a=d-h

a=493cm

Si l'on considère que a=d, on peut calculer la taille (L) de la projection au moment ou elle rencontrera le miroir et donc en conclure la taille du miroir. Dans notre cas, pour une distance (a) environ égale à 500cm, la taille (L) de l'image au niveau du miroir sera environ égale à 200cm. Pour un système qui se veut mobile, éphémère et le moins encombrant possible devoir placer un miroir de près de 2m ne semble pas être la meilleure des solutions, il me faudra donc trouver une autre solution pour arriver à agrandir la projection avec une hauteur sous plafond faible.

Intention

Dans un contexte où l'espace public est majoritairement fréquenté à des fins commerciales et où la retranscription à grande échelle par les médias de certains événements ou faits sportifs met en évidence des valeurs parfois en décalage avec l'éthique initiale du sport (cf. mémoire), j'ai envie de réaliser un projet prenant le contre-pied de ces faits, prônant des valeurs citoyennes à travers le sport.

Pour cela, j'ai voulu dans une première installation m'appuyer sur un sport me tenant tout particulièrement à cœur, le football, de par le plaisir qu'il m'apporte mais aussi de par le cadre d'apprentissage de valeurs qu'il a été et qu'il est pour moi. Au-delà de ce que cette pratique représente pour moi, c'est également le sport possédant le plus de licenciés en France et le sport populaire par excellence, c'est pourquoi le football m'est apparu comme la pratique sportive pouvant rassembler le plus grand nombre.

Mon intention est de réaliser un changement de fonction éphémère, facile et rapide, d'une partie d'un espace public pour en faire un lieu sportif afin de permettre aux citoyens de partager des moments de détente et de plaisir et pour favoriser le rapprochement des individus par le jeu/sport.

Afin de respecter cette volonté d'éphémérité nécessaire au respect des usages premiers de ces lieux et afin de ne pas dégrader ces lieux communs à tous, j'ai l'intention de représenter les limites/lignes/traces délimitant le “terrain de jeu” à l'aide de jeux de lumières/projections.

Remarque (ACC) : ne serait-il pas utile d'évoquer ici la ville connectée de demain comme cadre pour des initiatives individuelles et citoyennes de récupération d'une partie de l'organisation des activités sportives? Ce qui vise à mettre en relation “le passage à un nouveau seuil de complexité technique” et la “défonctionnalisation-refonctionnalisation” des liens et des pratiques (cf. Annick Lantenois, le Vertige du funambule)? Une autre question : quels seront les espaces de diffusion de ces intermèdes footballistiques citoyens? Le graphiste ici prévoit-il uniquement le dispositif technique qui permet ce changement d'usage des espaces publics ou en profite-t-il pour modifier la forme des tracés (une forme liée au matériau gazon (?) et à l'allocation d'un seul usage spécifique à un espace donné)? Vous proposez donc un nomadisme sportif et remettez en cause indirectement la sédentarisation des équipements…

Expérimentation 2

Code

 import processing.video.*;

Capture cam;
PGraphics img;

// variable globale choisie pour la couleur par défaut du traking
color selected = color(145,75,85); // selected color

void setup() 
{
  String[] devices = Capture.list();
  println(devices);
  
  size(displayWidth,displayHeight);
  background(255);
  smooth();
  cam = new Capture(this,displayWidth,displayHeight,"Appareil photo/caméra Logitech",30);
  cam.start();
  img = createGraphics(displayWidth,displayHeight,JAVA2D);  
}

void draw()
{
  if (cam.available()) {
    cam.read(); cam.loadPixels();
    
    // pick a different selected color, if you want
    if(mousePressed) selected = cam.pixels[mouseX+mouseY*cam.width];
    
    // search for the pixel closer to the selected color
    int sx = 0, sy = 0; // selected position
    float minDist = 10; // sensibilité de la detection de la couleur
    for(int y = 0; y < cam.height; y ++) {  
      for(int x = 0; x < cam.width; x ++) {
        color c = cam.pixels[x+y*cam.width];
        float d = dist(red(c),green(c),blue(c),
                       red(selected),green(selected),blue(selected));
        if(d < minDist) { minDist = d; sx = x; sy = y; }
      }
    }
    
    
    /// dessin du spot
    // update the painted image
    img.beginDraw();
    img.smooth();
    img.noStroke();
    
    color colorSpot = color(random(0,255),random(0,255),255); // couleur du spot de traking

    fill(colorSpot);
    img.fill(colorSpot);
    img.rect(sx,sy,random(10-100),random(10-100));  // taille et position du cercle utiliser pour dessiner

    img.endDraw();
    

    
    // draw the cam image and on top of that draw the painted image
    image(cam,0,0);    //afficher la vidéo en font
    image(img,0,0);      //afficher le dessin
    
  }
  
//ligne terrain
strokeWeight(5);
stroke(237,127,16);
noFill();
rect(2,2,1275,715);


//ligne centrale
strokeWeight(5);
stroke(237,127,16);
line(640,0,640,720);

//rectangle surface de réparation + arc de cercle gauche
strokeWeight(5);
stroke(237,127,16);
noFill();
ellipse(0,360,400,300);

strokeWeight(5);
stroke(237,127,16);
noFill();
rect(0,200,160,320);

strokeWeight(5);
stroke(237,127,16);
noFill();
rect(0,280,80,160);

fill(237,127,16);
ellipse(120,360,5,5);

//rectangle surface de réparation + arc de cercle droit
strokeWeight(5);
stroke(237,127,16);
noFill();
ellipse(1280,360,400,300);

strokeWeight(5);
stroke(237,127,16);
noFill();
rect(1120,200,160,320);

strokeWeight(5);
stroke(237,127,16);
noFill();
rect(1200,280,80,160);

fill(237,127,16);
ellipse(1160,360,5,5);

//rond central + point central
strokeWeight(5);
stroke(237,127,16);
noFill();
ellipse(640,360,300,300);

fill(237,127,16);
ellipse(640,360,5,5);

//corner
strokeWeight(5);
stroke(237,127,16);
noFill();
ellipse(0,0,60,60);

strokeWeight(5);
stroke(237,127,16);
noFill();
ellipse(0,720,60,60);

strokeWeight(5);
stroke(237,127,16);
noFill();
ellipse(1280,0,60,60);



strokeWeight(5);
stroke(237,127,16);
noFill();
ellipse(1280,720,60,60);  
}

void keyPressed() {
  // réinitialiser la page
  if(key == ' ') img = createGraphics(cam.width,cam.height,JAVA2D);
}

Liens

Terrain laser

Tracés lumineux

Anthropométrie

Anthony McCall :-/ ce lien ne fonctionne pas (ACC)et d'ailleurs toujours pas plusieurs moi plus tard… :-(

Vidéo Matthew Barney

Hilka Nordhausen

Pour aller plus loin

Dans quel contexte fonctionne cette installation ? Pour quelle cible ? À quelle échelle ? Quelle utilisation des traces obtenues ? Fins pédagogiques ? Découverte de l'image ? Iconographie? Vidéo?

Liste des jeux réalisé par les enfants de l'École Jules Ferry à Villeneuve-Saint-Georges : Liste des jeux


wiki/projets/athletagraphie/athletagraphie.txt · Dernière modification: 2015/06/21 17:09 (modification externe)