====== 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 ====== {{ :wiki:projets:athletagraphie:mg_7332.jpg?direct&300 |}} {{ :wiki:projets:athletagraphie:mg_7346.jpg?direct&300 |}} {{ :wiki:projets:athletagraphie:mg_7354.jpg?direct&300 |}} {{ :wiki:projets:athletagraphie:mg_7355.jpg?direct&300 |}} ====== Vidéo ====== {{vimeo>119976633?medium}} 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 ** {{ :wiki:projets:athletagraphie:athletagraphie_sketch_bb.jpg?direct&300 |}} ** 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. {{ :wiki:projets:athletagraphie:sche_ma1.jpg?direct&300 |}} {{ :wiki:projets:athletagraphie:sche_ma2.jpg?direct&300 |}} {{ :wiki:projets:athletagraphie:courbe.jpg?direct&300 |}} 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====== [[http://www.designboom.com/technology/nikes-laser-beam-soccer-field-lets-you-play-at-night/|Terrain laser]] [[http://www.fubiz.net/2015/01/03/light-installations-by-carlo-bernardini/|Tracés lumineux]] [[http://www.laboratoiredugeste.com/spip.php?article28/|Anthropométrie]] [[http://www.skny.com/artists/anthony-mccall/images//|Anthony McCall]] :-/ ce lien ne fonctionne pas (ACC)et d'ailleurs toujours pas plusieurs moi plus tard... :-( [[https://www.youtube.com/watch?v=83WTxmkye04|Vidéo Matthew Barney]] [[http://www.hilkanordhausen.de/?q=node/152|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 : [[http://pbmedias.free.fr/jeux/vsg_france_ecole-jferry/vsg_ecole-jferry_00_recreation.htm|Liste des jeux]] ----