Affichage des articles dont le libellé est code. Afficher tous les articles
Affichage des articles dont le libellé est code. Afficher tous les articles

03/02/2018

Quand l'environnement s'adapte à moi.


Aurélien du FAbLAB... a sollicité lesBricodeurs pour un atelier à la cité du Design.
Son idée étant d'illustrer de manière concrète une des possibilités de lier les données personnelles (issues de la personne, de capteurs physiques  --> environnement)

Un capteur de rythme cardiaque qui modifierait une playlist : plus le rythme cardique est lent, plus la musique est lente et inversement.

--> Arduino Yun avec lininoio

LA LIAISON CAPTEUR APPLI-WEB

Premier code côté javascript (node, express, socket.io, librairie lininoio, avant la réception du capteur, avec un potentiomètre branché sur A0 pour simuler les variations 


       
//https://github.com/ideino/ideino-linino-lib

///////////////////////////////////////////////////////////
// GESTION NODE EXPRESS SERVEUR
///////////////////////////////////////////////////////////
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var port = process.env.PORT || 3006;

///////////////////////////////////////////////////////////
// GESTION DES COMMANDES LINUX comme reboot
///////////////////////////////////////////////////////////
//var exec = require('child_process').exec;

///////////////////////////////////////////////////////////
// GESTION DE LA CARTE ARDUINO
///////////////////////////////////////////////////////////
var linino = require('ideino-linino-lib'),
board = new linino.Board(),
html = new linino.Htmlboard();
//var servoH = { pin: board.pin.servo.S9, value : 180 };
//var pin13 = board.pin.digital.D13;
var pot = board.pin.analog.A0;

// Routing
app.use(express.static(__dirname + '/public'));

//LANCEMENT SERVEUR
server.listen(port, function () {
 console.log('Server listening at port %d', port);
 console.log('potentiometre : A0');
 
});




board.connect(function(){
 console.log('CARTE Connected');
 io.on('connection', function (socket) {
  console.log("CLIENT connected");
  
  
  board.analogRead(pot, function(value){
   console.log('value: ' + value);
  // var data = {"AO": value};
   socket.emit('update', value);
  });
 });
 
}); 


accompagné d'un fichier /public/index.html qui fait appel aux librairies P5JS, socket.io :
https://github.com/scenaristeur/lininoapps/blob/master/root/cardio/public/index.html


       
<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0>
    <style> body {padding: 0; margin: 0;} </style>
    <script src="lib/p5.min.js"></script>
    <script src="lib/addons/p5.dom.min.js"></script>
    <script src="lib/addons/p5.sound.min.js"></script>
    <script src="js/sketch.js"></script>
  </head>
  <body>
  
  <script src="/socket.io/socket.io.js"></script>
  <script>
 var socket = io();
 console.log(socket);
 /*socket.on('update', function (data) {
  console.log(data);
 });*/
  
  </script>
  </body>
</html>


Et un fichier p5js /public/js/sketch.js :
https://github.com/scenaristeur/lininoapps/blob/master/root/cardio/public/js/sketch.js

Qui référence les chansons (sotckées dans le dossier /assets) selon leur BPM .
Comme d'hab : setup met en place l'environnement et définit le listener de la communication bi-directionnelle entre la page web et le serveur grâce au listener  'socket.on("update", function(data){...});




var bpm = 0
var play = false;
// convertisseur mp3 : http://youtubemp3.to/
// bpm search : https://songbpm.com/        https://www.bpmdatabase.com/music/search/?artist=&title=&bpm=70&genre=
// p5js playsound https://p5js.org/examples/sound-load-and-play-sound.html


var song ;
var ROAR_90, GETLUCKY_116, COME_100, WALK_105, CARMEN_150, CRUEL_168;
var slider;

function preload() {
 // soundFormats('mp3', 'ogg');
 // trover des chansons de 40 BPM à 220
  ROAR_90 = loadSound('assets/90BPM - Katy Perry - Roar Official.mp3');
 COME_100 = loadSound('assets/100BPM - Jain - Come.mp3');
 WALK_105 = loadSound('assets/105BPM - Lou Reed - Walk On The Wild Side.mp3');
 GETLUCKY_116 = loadSound('assets/116BPM - Daft Punk - Get Lucky.mp3');
 CARMEN_150 = loadSound('assets/150BPM - Stromae - carmen.mp3');
 CRUEL_168 = loadSound('assets/168BPM - Elvis Presley - Dont Be Cruel.mp3');
 console.log("chansons chargées");
}

function setup() {
 canvas = createCanvas(windowWidth, windowHeight);
 slider = createSlider(40, 220, 70);
 slider.position(10, 10);
 
 slider.style('width', width/2+'px');
 
 
 
 song = ROAR_90;
 fft = new p5.FFT();
 song.amp(0.2);
 //GETLUCKY_116.play();
 // GETLUCKY_116.pause();
 
 console.log("ready");
 console.log(socket);
   socket.on('update', function (data) {
  
  //var json = JSON.parse(data);
  
  bpm = Math.round(map(data,0,1023,40,220));
  console.log(bpm);
  slider.value(bpm);
  changeSong(ROAR_90, bpm, 80, 95);
  changeSong(COME_100, bpm, 95, 102);
  changeSong(WALK_105, bpm, 102, 110);
  changeSong(GETLUCKY_116, bpm, 110, 120);
  changeSong(CARMEN_150, bpm, 120, 160);
  changeSong(CRUEL_168, bpm, 160, 220);
 });
}

function draw() {
 var color = map(bpm,40,220,0,255);
 background(color);
 noStroke();
 //fill(255-color);
 fill(bpm, 255-bpm, 0);
 ellipse(width/2,height/2,bpm,bpm); 
 text(bpm,100,100);
 
 //visu
 var spectrum = fft.analyze();
 noStroke();
 fill(0,255,0); // spectrum is green
 for (var i = 0; i< spectrum.length; i++){
  var x = map(i, 0, spectrum.length, 0, width);
  var h = -height + map(spectrum[i], 0, 255, height, 0);
  rect(x, height, width / spectrum.length, h )
 }
 
 var waveform = fft.waveform();
 noFill();
 beginShape();
 stroke(255,0,0); // waveform is red
 strokeWeight(1);
 for (var i = 0; i< waveform.length; i++){
  var x = map(i, 0, waveform.length, 0, width);
  var y = map( waveform[i], -1, 1, 0, height);
  vertex(x,y);
 }
 endShape();
 
}


function changeSong(s, bpm, min, max){
 if ((bpm > min ) && (bpm <= max) && (song != s )){
  //ROAR_90.pause();
  song.pause();
  song = s;
  song.play()
  console.log(s);
 }
 
 
}


function mousePressed() {
 play = !play;
 console.log(play);
 if (play){
  console.log("play");
  song.play();
  
  }else{
  console.log("stop");
  song.stop();
 }
 }  


TRANSFORMATION DU SIGNAL

Une fois le capteur reçu, la difficulté était de récupéréer le rythme cardiaque . En effet, le code de base http://learn.linksprite.com/arduino/advanced-learning-kit-for-arduino/how-to-use-heatbeat-sensor-module-on-arduino/ permet de mesurer la variation d'oxygène contenue dans le sens. Il a fallu transformer le signal pour calculer une moyenne du nombre de battements par minutes.

Code de base pour Arduino :

       
// Pulse Monitor Test Script
 
int ledPin = 13;
 
int sensorPin = 0;
 
double alpha = 0.75;
 
int period = 20;
 
double change = 0.0;
 
void setup()                   
 
{
 
  pinMode(ledPin, OUTPUT);
 
  Serial.begin(115200);
 
}
 
void loop()                    
 
{
 
    static double oldValue = 0;
 
    static double oldChange = 0;
 
    int rawValue = analogRead(sensorPin);
 
    double value = alpha * oldValue + (1 - alpha) * rawValue;
 
    Serial.print(rawValue);
 
    Serial.print(",");
 
    Serial.println(value);
 
    oldValue = value;
 
    delay(period);
 
}









[ en cours de rédaction ]










05/01/2018

Tutoriel slither.io sur P5JS

English Translation of this article ]

Objectif : recréer un jeu inspiré de slither.io.


Découverte de l'éditeur P5js online

Commencez par ouvrir l'éditeur P5js online : https://alpha.editor.p5js.org/
Vous devriez voir le code suivant :


       
function setup() { 
  createCanvas(400, 400);
} 

function draw() { 
  background(220);
}

Dans P5js, deux fonctions sont importantes : la fonction 'setup' qui permet de mettre en place l'environnement et la fonction 'draw' qui boucle à l'infini.

Dans 'setup', la fonction 'createCanvas(400, 400)' définit un espace de 400 pixels de largeur par 400 pixels de hauteur. Notez que chaque instruction se termine par un point virgule ';'.

Dans 'draw', la fonction 'background' définit la couleur de fond.

Dans l'éditeur p5js online, cliquez sur le bouton 'PLAY' (triangle rose sur fond gris) pour exécuter votre code. Un carré gris ( background(220); ) de 400 pixels de largeur par 400 pixels de hauteurs ( createCanvas(400, 400); ) devrait apparaître sur la droite.
Le carré juste à droite du bouton 'PLAY' est le bouton 'STOP' et est utilisé pour stopper l’exécution de votre code.

Notez que chaque définition de fonction commence par le mot 'function', suivi du nom de la fonction, ensuite, nous avons deux parenthèses '()' permettant éventuellement de définir des paramètres pour la fonction, et le corps de la fonction contenu entre deux accolades '{ }'.

Premiers essais

On peut à ce stade faire déjà quelques essais. Par exemple, vous pouvez : 
- remplacer createCanvas(400, 400);  par createCanvas(600, 600); pour agrandir le canvas ou 
- remplacer  background(220); par background(10, 150, 100);
  pour changer la couleur de fond en un vert. Choisissez maintenant la couleur qui vous convient. De nombreuses palettes existent sur internet pour choisir vos couleurs.

Note : La définition des couleurs sous P5js :
Il existe trois manière de définir les couleurs dans p5js : 
- 1 nombre compris entre 0 et 255 : un niveau de gris, avec 0 correspondant à noir et 255 correspondant à blanc;
- 3 nombres compris entre 0 et 255 séparés par des virgules : ici on définit un mélange des trois couleurs 'rouge', 'vert', 'bleu'.
- 4 nombres compris entre 0 et 255 : idem que précédemment, le quatrième paramètre définissant la transparence.


Contrôles du jeu


Dans slither.io, on joue avec la souris. On va donc avoir besoin des coordonnées de la souris. Sous P5js, elles sont définies par les variables 'mouseX' et 'mouseY'.

Note : Le manuel de référence :
Pour avoir un aperçu des fonctionnalités existantes dans P5js, consultez le manuel de référence... par exemple pour 'mouseX' , c'est ici https://p5js.org/reference/#/p5/mouseX et pour mouseY, c'est ici : https://p5js.org/reference/#/p5/mouseY

On va en profiter pour dessiner un premier petit truc, un cercle, ou une ellipse

Note: Dessiner une ellipse :
Pour une ellipse, on définit 3 ou 4 paramètres (le quatrième, la hauteur est optionnelle) 
extrait du manuel de référence :  ellipse(x,y,w,[h])
x pour l'abscisse de l'ellipse, y pour l'ordonnée, w pour sa largeur et h sa hauteur. Les crochets autour du 'h' indiquent que ce paramètre est optionnel.

Juste après la ligne background, insérer la ligne :

ellipse(mouseX, mouseY,10);

Vous devriez obtenir ce code :

       
function setup() {

  createCanvas(600, 600);

}



function draw() {

   background(10, 150, 100);

  ellipse(mouseX, mouseY, 10);

}


Exécutez-le en cliquant sur le triangle rose. En bougeant la souris sur le canvas, vous devriez voir un petit point blanc suivre votre souris... C'est l'ellipse qui a les même coordonnées que votre souris... Facile, non ???


vous pouvez changer la forme de cette ellipse, en lui ajoutant un quatrième paramètre (le 'h' optionnel de tout à l'heure, en modifiant la valeur de sa largeur ('w'), ou en modifiant sa couleur. Pour changer la couleur, insérez juste avant la ligne ellipse(mouseX, mouseY, 10);  une ligne utilisant la fonction 'fill' ( fill = remplissage )  . Par exemple, en insérant  fill(100, 100, 240)vous colorerez votre ellipse en violet (100 pour rouge, 100 pour vert et 240 pour bleu).

notre fonction draw devrait maintenant contenir le code suivant : 

       
background(10, 150, 100);

  fill(100, 100, 240);

  ellipse(mouseX, mouseY,10);




L'objet 'Nourriture'


Notre slither suit notre souris, première étape remplie, mais maintenant, il va lui falloir quelque nourriture à manger...

Pour ce faire, on va créer une 'Classe'. Sous P5js une classe va nous permettre de créer un objet que l'on pourra réutiliser par la suite. Une classe se créé comme une fonction.
Un 'grain' de nourriture sera dans un premier temps matérialisé par un petit carré positionné au hasard dans le canvas. Pour le hasard, on va ici user de la fonction 'random'
Après l'accolade de fermeture de la fonction draw(){...} collez le code de la fonction 'Nourriture'. Notez la majuscule, c'est un signe distinctif pour différencier les Classes des fonctions de base.

function setup() { 
  createCanvas(600, 600);
} 

function draw() { 
   background(10, 150, 100);
  fill(100, 100, 240);
  ellipse(mouseX, mouseY,10);
}

function Nourriture(){
  this.x = random (10, width-10);
  this.y = random (10, height-10);
  this.color =  color(random(0,255),random(0,255),random(0,255));
 
}

Note : Mais qu'est-ce que ce 'this' ??? 
'This' est ici pour définir une variable interne à la classe... 'this.x' on définit l'abscisse propre à notre objet 'Nourriture', comme 'this.y' définit son ordonnée et 'this.color' ... sa couleur, notez ici la manière de définir une couleur aléatoire, en prenant un random en 0 et 255 pour chacune des trois couleurs.

Mais ceci ne suffit pas encore pour voir notre objet 'Nourriture', nous devons également lui créer une fonction interne que nous appelerons 'display', ou plutôt 'this.display' car c'est une fonction interne à l'objet. 
A vous de bosser, je vous donne le code, essayez de deviner ce qu'il fait, reportez-vous éventuellement au manuel de référence

 this.display = function(){
    stroke(color(random(0,255),random(0,255),random(0,255)));
    strokeWeight(1);
    fill(this.color);
    rect(this.x, this.y, 5,5);
    noStroke();
  }

Bon ok, pour ceux qui se seraient perdus ou aurait la flemme : 
- stroke() définit la couleur du contour de l'élément qui va suivre.
- strokeWeight() définit son épaisseur
- fill() : remplissage comme vu précédemment, ici on remplit avec 'this.color'
- rect(), on dessine un rectangle à la position aléatoire (this.x, this.y,..) définie lors de la création de l'objet 'Nourriture' , les troisième et quatrième paramètre définissent comme pour l'ellipse, la largeur et la hauteur du rectangle.
- noStroke(); est ici utilisé pour enlever le contour pour les prochains objets. (On ne sait pas à ce stade ce qui sera dessiné après le rectangle, donc précaution).

Nous avons maintenant une fonction pour dessiner notre objet 'Nourriture', mais il n'existe pas encore. Nous allons pour ce faire, créer une variable 'nourriture', sans majuscule, cette fois, avant la fonction 'setup', car c'est une variable 'global' (on pourra l'utiliser n'importe où dans notre code ).

var nourriture; 

ensuite, il ne reste plus qu'à l' 'implémenter' dans la fonction 'setup' en utilisant le code :
(implémenter = définir notre variable 'nourriture' comme étant un nouvel objet de la Classe  'Nourriture', grâce au mot clé "new") 

nourriture = new Nourriture();

et à demander son affichage dans la fonction 'draw' 

nourriture.display();

Si votre code est le même que celui qui suit, vous devriez voir maintenant un cube 'clignotant' placé de manière aléatoire et représentant un 'grain' de nourriture : 


       
var nourriture;



function setup() {

  createCanvas(600, 600);

 nourriture = new Nourriture();

}



function draw() {

   background(10, 150, 100);

  fill(100, 100, 240);

  ellipse(mouseX, mouseY,10);

  nourriture.display();

}



function Nourriture(){

  this.x = random (10, width-10);

  this.y = random (10, height-10);

  this.color =  color(random(0,255),random(0,255),random(0,255));

 

 this.display = function(){

    stroke(color(random(0,255),random(0,255),random(0,255)));

    strokeWeight(1);

    fill(this.color);

    rect(this.x, this.y, 5,5);

    noStroke();

  }

}




Ajouter un adversaire qui sera déplacé par le clavier

Si on veut jouer avec un ami, on peut imaginer un adversaire que le serpent ne devra pas rencontré... Allez donc voir sur cette page : http://www.lyceelecorbusier.eu/p5js/?p=2019#more-2019  le paragraphe indiquant "Pour déplacer un élément au clavier avec les flèches directionnelles utiliser UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW."


Déterminer si la nourriture a été croquée

Si vous êtes arrivé là, allez jeter un oeil au code un peu plus évolué, et tentez de la modifier : http://smag0.blogspot.fr/2017/12/code-slitherio-pour-p5js.html

Des fonctionnalités de jeux plus avancées avec P5Play


Pour faciliter le développement de jeux, des librairies P5js existent, comme la librairie P5play :
voyez par exemple le jeu asteroids développé avec p5play.
D'autres librairies existent pour P5js : https://p5js.org/libraries/

OpenProcessing
OpenProcessing est une galerie d'animations réalisées avec P5js ou Processing et est accessible à  cette adresse : https://www.openprocessing.org/browse/#















11/12/2017

Code slither.io pour P5js

Un petit bout de code pour p5.js,  inspiré de slither.io, pour les CM1 /CM2 de l'école la Rédemption qui apprennent à coder.
Allez voir le tutoriel, pour comprendre la logique de ce code et pouvoir l'adapter selon vos envies .

code à copier dans l'interface p5js editor :

  1. sélectionnez tout le code ci-dessous
  2. Ctrl+C pour copier
  3. rendez-vous ensuite sur l'éditeur  p5js editor : 
  4. Ctrl+V pour coller
  5. puis lancez en cliquant sur le triangle.
  6. vous pouvez ensuite modifier ce code pour adapter le jeu selon vos envies, n'oubliez pas le site p5.js pour quelques explications sur les fonctions utilisées : P5JS / Référence
       
var serpent;
var positions = [];
var nourriture;
//var mechantSerpent; //pour créer un adversaire ?

function setup() {
  fullscreen();
  createCanvas(800, 600);
  serpent = new Serpent();
//  mechantSerpent = new Serpent();
  nourriture = new Nourriture();
  positions[positions.length] = {mouseX,mouseY};
  textSize(32);
}

function draw() {
  background(0);
  tick();
  serpent.move();
  serpent.display();
  nourriture.display();
  nourriture.croque();
  fill(0, 102, 153);
  text( serpent.corps.boules.length-1, width-100, 30);
}

// serpent
function Serpent() {
  this.x = random(width);
  this.y = random(height);
  //  positions[0].x = this.x;
  //  positions[0].y = this.y;
  this.diameter = random(10, 30);
  this.speed = 1;
 this.corps = new Corps();
 var tete = new Boule(mouseX, mouseY,  color(random(0,255),random(0,255),random(0,255)));
 this.corps.boules[0] = tete;
 console.log(this.corps);

  this.move = function() {
    var boules = this.corps.boules;
  for (var i = 0; i < boules.length; i++) {
    var b = boules[i];
     if (i == 0){
          b.x = positions[0].x;
        b.y = positions[0].y;
          if (positions.length > 1 ){
            positions.shift();
          }
   }else{
        var precedente = boules[i-1];
        var d = int(dist(b.x, b.y, precedente.x, precedente.y));
        if(d > 10){
          if(b.x - precedente.x > 0){
            b.x = (3*b.x+ precedente.x)/4 ; // b.x-1-(d/20);
          }else if (b.x - precedente.x < -0) {
            b.x = (3*b.x+precedente.x)/4; //b.x+1+(d/20);
          }
          if (b.y - precedente.y > 0){
            b.y = (3*b.y + precedente.y)/4; //b.y-1-(d/20);
          }else if(b.y - precedente.y < -0){
            b.y = (3*b.y+precedente.y)/4; //b.y+1+(d/20);
          }
        }
   }
  }
  };

  this.display = function() {
    var boules = this.corps.boules;
  for (var i = 0; i < boules.length; i++) {
      var b = boules[i];
        fill(b.color);
        ellipse(b.x, b.y, this.diameter, this.diameter);
      }
      fill(boules[0].color);
      strokeWeight(1);
      stroke(color(0));
      ellipse(boules[0].x, boules[0].y, this.diameter*1.2, this.diameter*1.2);
      ellipse(boules[0].x, boules[0].y+this.diameter/4, this.diameter/3, this.diameter/4);
   }
}


function Corps(){
 this.boules = [];
}

function Boule(_x,_y, _color){
 this.x = _x;
 this.y = _y;
  this.color = _color;
}

function tick(){
  var longueurPos = 40;
  if (positions.length > longueurPos ){
    positions.shift();
  }
  if ((positions[positions.length-1].x != mouseX)&& (positions[positions.length-1].y != mouseY)){
    var pos = {};
    pos.x = mouseX;
    pos.y = mouseY;
    positions[positions.length] = pos;
  }else{
    if (positions.length > 1 ){
      positions.shift();
    }
  }
}

function Nourriture(){
  this.x = random (10, width-10);
  this.y = random (10, height-10);
  this.color =  color(random(0,255),random(0,255),random(0,255));

  this.display = function(){
    stroke(color(random(0,255),random(0,255),random(0,255)));
    strokeWeight(1);
    fill(this.color);
    rect(this.x, this.y, 5,5);
    noStroke();
  }

   this.croque = function(){
    var serpentTete = serpent.corps.boules[0];
    var d = int(dist(this.x, this.y, serpentTete.x, serpentTete.y));
    if (d < 10 ){
      var nouveau = new Boule(mouseX, mouseY, this.color);
      var longueur = serpent.corps.boules.length;
      serpent.corps.boules[longueur] = nouveau;
      nourriture = new Nourriture();
    }
  }
}

08/08/2015

DreamCatcher, l'attrape rêves

DreamCatcher est une application gratuite opensource permettant de transmettre des informations aux objets connectes et autres robots de ma maison.
Par extension, elle peut être utilisée pour présenter et partager ses idées entre les humains également ;-) .

La dernière version 1 est accessible ici : http://smag-smag0.rhcloud.com/DreamCatcher .
ou plus facile à retenir (http://goo.gl/tViQ3Q) ... "t'es vicu trois culs avec t et i en minuscule" ;-D
(Le développement sur smartphone n'est pas encore totalement implémenté, à utiliser sur PC avec Chrome ou Firefox).
 [ Nouvelle version en cours de développement avec P5js en 3D : http://smag0.blogspot.fr/2015/12/dreamcatcher-ou-comment-partager-des.html ]

[ v1,v2 ou v3 ? faisons le point sur les versions de Dreamcatcher : http://smag0.blogspot.fr/2016/02/dreamcatcher-v3-integration-dans-meteor.html ]

Historique : 

L'idée de départ était de créer une interface pour le projet Smag0 (un robot qui range ma chambre).

Pour Smag0, nous avons besoin d'une interface simple pour transmettre des informations au robot (ou groupe de robots, objets connectes...) qui serait en mesure de ranger notre chambre, puisque c'est le but du projet.


Pour que ces "futurs hypothétiques robots" communiquent et échangent des informations, il a été pris parti de formater les informations au format RDF/OWL, ces informations décrivent des relations entre deux concepts, plutôt qu'un concept seul, sous forme de triplet.
(voir : Robolution + Homme 2.0 = Information 2.0)



Au départ, donc, cette interface devait servir, pour l'utilisateur, à transmettre facilement des informations à la maison, qui les partagerait ensuite avec les différents robots et objets connectés que l'on pourrait avoir dans notre maison.

Par extension, et au fil des développement, je me suis aperçu qu'elle pouvait également être utile pour exposer ses idées et les visualiser sous forme de graphes. Il est alors plus facile de partager ses idées.
Un petit schéma valant toujours mieux qu'un long discours, le graphe donne la possibilité d'atteindre directement l'information qui nous intéresse, et de cerner rapidement les informations qui sont liées.

Cette application dont le but est de faciliter la captation de mes idées ou de mes rêves a donc un nom tout trouvé : DreamCatcher (Attrape Revês)...

Le code source pour ceux qui voudraient modifier l'application est disponible en bas de la page de l'application.


Utilisation : 

L'utilisation de DreamCatcher est très simple.

Ouverture : 

A l'ouverture, un jeu de données est présent. Il suffit de cliquer dans l'espace de travail pour que le graphe correspondant à ces données prenne forme.
On peut alors zoomer avec la flèche "haut" du clavier et dézoomer avec la flèche "bas". Avec la souris, on peut aussi déplacer le graphe pour consulter une zone particulière.
La barre "espace" de votre clavier rétablit la position initiale.
Voir l'aide pour plus de fonctionnalités (nouveau graphe, sauvegarde du graphe sous forme d'image...)

Les données correspondantes au graphe apparaissent sur la droite sous forme de blocs bleus en dessous de "Dernière Activité".
Elles sont déjà enregistrées sous forme de triplet {sujet, prédicat, objet}.



En cliquant sur l'un de ces blocs bleus, vous le sélectionnez, il passe alors directement dans l'espace "Informations sélectionnées" et devient vert.
En même temps, la partie du graphe correspondant à cette information s'éclaire dans le graphe (si le graphe ne s'actualise pas automatiquement, cliquez à l'intérieur de l'espace de travail) :

  • le sujet du triplet en jaune,
  • la propriété (ou prédicat) en vert,
  • et l'objet du triplet en bleu.

Vous pouvez sélectionner plusieurs informations en même temps et les voir apparaître dans le graphe.
Pour les faire disparaître, il suffit de les désélectionner en cliquant sur le bloc vert correspondant. L'information redescend automatiquement dans l'espace "Dernière Activité" et redevient bleue .


Créer un nouveau Graphe

Pour créer un nouveau graphe, il suffit de cliquer dans l'espace de travail pour être certain qu'il soit bien activé, et de presser la touche "n" de votre clavier. (la touche "d" permet de recharger la démo).

Lorsque vous pressez la touche "n", l'espace de travail est nettoyé, et vous pouvez glisser les blocs "Chose/Thing" dans l'espace de travail pour décrire une nouvelle chose, idem pour "Acteur" et "Environnement"... ("Un type de chose" correspondant à une classe au sens OWL)

D'autres fonctionnalités sont en cours de développement, comme la modification des informations, l'ajout de propriétés à un sujet, la visualisation à différents niveaux, la recherche de liens avec les vocabulaires et bases de données existants (http://wiki.dbpedia.org/online-access/DBpediaLivehttp://lov.okfn.org/dataset/lov/), la création de sessions où l'on peut travailler à plusieurs sur le même graphe, l'utilisation de l'interface DreamCatcher pour fusionner les idées comme évoqué ici : https://www.linkedin.com/pulse/large-concept-collider-georges-le-nigen , une interface mobile permettant d'enregistrer messages vocaux et formater infos pour DreamCatcher...

N'hésitez pas proposer des modifications ou critiquer, proposez également de nouvelles fonctionnalités, et surtout dites-moi ce que vous n'avez pas compris... c'est le meilleur moyen de faire avancer les choses, et de proposer une interface la plus accessible possible pour proposer cette application aussi bien à mon fils de 8 ans qu'à ma grand-mère de 70 ans... ;-) 

Utilisez les commentaires au bas de cet article ou l'espace de discussion prévu à cet effet : https://groups.google.com/forum/#!topic/smag0/HpqEGB7cH4g


Accéder à DreamCatcher http://goo.gl/tViQ3Q

 [ Nouvelle version en cours de développement avec P5js : http://smag0.blogspot.fr/2015/12/dreamcatcher-ou-comment-partager-des.html ]


[... Document en cours de création...]

26/03/2015

Sphero with Processing

For some days, i'm trying to use Processing to drive Sphero, with this code (Working on Windows) :

import processing.serial.*;

Serial Serialout ;
Serial Serialin;

void setup() {
  // List all the available serial ports:
  println(Serial.list());
  Serialout = new Serial(this, Serial.list()[0], 115200); // COM3 output SPHERO-BPG 'RN-SPP'
  Serialin = new Serial(this, Serial.list()[1], 115200); // COM4 input SPHERO-BPG
  println("Sphero turns blue, --> it is connected to output "+Serialout);
  println("Sphero turns blue, --> it is connected to input "+Serialin);
}

void draw() {
  while (Serialin.available ()>0) {
    println(Serialin.read());
  }
  while (Serialout.available ()>0) {
    println(Serialout.read());
  }
  // print ("but there is no data to read ! GRRRRR!");
}

void keyPressed() {
  Serialout.dispose();
}



Sphero is connected because it turns blue, and disconnected when I press a key, but i can't read/send any data using https://www.processing.org/reference/libraries/serial/ or other bluetooth library.
I don't understand how I could get SpheroName, and other info, how to send commands ?

Could someone help me ?