Tuesday, March 22, 2016

Kinect Arduino Robot

Bonjour, Comme il est indiqu� au titre de cette article je vais aujourd'hui illustrer les �tapes � suivre pour r�aliser un robot, un syst�me manipul� en g�n�rale guid� et command� par ce qu'on appelle Kinect.



Commen�ons tout d'abord par d�finir Kinect pour ceux qui les connaissent pas encore:
R�sultat de recherche d'images pour "kinect game"
Il s�agit en faite d�une cam�ra bas�e  sur des techniques d�interaction d�velopp�es par la soci�t� PrimeSense, nomm�e avant par le nom de code du projet, � Project Natal �, Elle est bas�e sur un p�riph�rique d�entr�e branch� avec la console Xbox 360 qui permet d�interagir par une certaine commande vocale, reconnaissance de mouvement et d�image.
R�sultat de recherche d'images pour "kinect"
On peut ainsi jouer sur des jeux sp�cialement d�velopp�s pour le projet, donc sans aucune manette ni p�riph�rique autre que son propre corps. Cette d�tection de mouvements sans p�riph�riques �tait d�j� pr�sente dans l�EyeToy de Sony.Ce vid�o vous montrerez comment �a fonctionne le kinect
Le 21 octobre 2010, Microsoft d�voile la premi�re publicit� officielle de son nouveau p�riph�rique, montrant � quel point la firme vise le grand public. Le g�ant de l'informatique a confirm� d�penser plus de 500 millions de dollars en marketing pour s'assurer de toucher au maximum la population.
Initialement hostile au portage du Kinect sur les PC, la soci�t� Microsoft a finalement chang� d'avis et a introduit Kinect pour Windows au 1er f�vrier 2012. Pour un prix sensiblement sup�rieur, cette version pour PC inclut de nouvelles fonctionnalit�s (par exemple le capteur a �t� repens� pour fonctionner � partir d�une distance de 50 cm. Kinect pour Windows inclut un kit de d�veloppement afin de permettre aux d�veloppeurs de cr�er leurs propres applications.
Revenons maintenant au caract�ristiques principales de cette cam�ra si d�velopp�e :
  • Capteur :
    • Lentilles d�tectant la couleur et la profondeur
    • Micro � reconnaissance vocale
    • Capteur motoris� pour suivre les d�placements
  • Champ de vision :
    • Champ de vision horizontal : 57 degr�s
    • Champ de vision vertical : 43 degr�s
    • Marge de d�placement du capteur : � 27 degr�s
    • Port�e du capteur : 1,2 m � 3,5 m (� partir de 50 cm pour la version Kinect for Windows)
  • Flux de donn�es :
    • 320 � 240 en couleur 16 bits � 30 images par seconde
    • 640 � 480 en couleur 32 bits � 30 images par seconde
    • Audio 16 bits � 16 kHz
  • Syst�me de reconnaissance physique :
    • Jusqu�� 6 personnes et 2 joueurs actifs (4 joueurs actifs avec le SDK 1.0)
    • 20 articulations par squelette
    • Application des mouvements des joueurs sur leurs avatars Xbox Live
  • Audio :
    • Chat vocal Xbox Live et chat vocal dans les jeux (n�cessite un compte Xbox Live Gold)
    • Suppression de l��cho
    • Reconnaissance vocale multilingue (pour les fran�ais, cette fonction est disponible depuis le 06 d�cembre 2011 via une M�J de la Xbox ).


L'objectif de notre projet c'est de savoir relier ce kinect avec une prototype Electronique compos�e d'une carte Arduino uno simple et 4 servomoteurs de fa�on savoir traiter l'information revenante de ce kinect et la traduire en mouvement instantan�, intelligent et direct.

Pour ceci on eu besoin de r�aliser une interface graphique sur processing (Download here) de but a faire afficher la squelette d��tre humain capt�e par kinect, d'autre plan de capt� les articulations logiques des ces organes (bras, �paules,main,....)

Comme premier plan on a arriv� a faire traduire les informations prises par kinect en 4 Angles principales (Epaule et coude droites Angles et Epaule et coude gauche angles).
Le programme processing est si dessous:



// Kinect Robot Processing Program

import SimpleOpenNI.*;
SimpleOpenNI kinect;
import processing.serial.*;
Serial port;
void setup() {
size(640, 480);
kinect = new SimpleOpenNI(this);
kinect.enableDepth();
kinect.enableUser();
kinect.setMirror(true);
println(Serial.list());
String portName = Serial.list()[0];
port = new Serial(this, portName, 9600);

}
void draw() {
kinect.update();
PImage depth = kinect.depthImage();
image(depth, 0, 0);
IntVector userList = new IntVector();
kinect.getUsers(userList);
if (userList.size() > 0) {
int userId = userList.get(0);
if ( kinect.isTrackingSkeleton(userId)) {drawSkeleton(userId);

// get the positions of the three joints of our arm
PVector rightHand = new PVector();
kinect.getJointPositionSkeleton(userId,
SimpleOpenNI.SKEL_RIGHT_HAND,
rightHand);
PVector rightElbow = new PVector();
kinect.getJointPositionSkeleton(userId,
SimpleOpenNI.SKEL_RIGHT_ELBOW,
rightElbow);
PVector rightShoulder = new PVector();
kinect.getJointPositionSkeleton(userId,
SimpleOpenNI.SKEL_RIGHT_SHOULDER,
rightShoulder);
// we need right hip to orient the shoulder angle
PVector rightHip = new PVector();
kinect.getJointPositionSkeleton(userId,
SimpleOpenNI.SKEL_RIGHT_HIP,
rightHip);
// reduce our joint vectors to two dimensions
PVector rightHand2D = new PVector(rightHand.x, rightHand.y);
PVector rightElbow2D = new PVector(rightElbow.x, rightElbow.y);
PVector rightShoulder2D = new PVector(rightShoulder.x,
rightShoulder.y);
PVector rightHip2D = new PVector(rightHip.x, rightHip.y);
// calculate the axes against which we want to measure our angles
PVector torsoOrientation =
PVector.sub(rightShoulder2D, rightHip2D);
PVector upperArmOrientation =
PVector.sub(rightElbow2D, rightShoulder2D);
// calculate the angles between our joints
float shoulderAngle = angleOf(rightElbow2D,
rightShoulder2D,
torsoOrientation);
float elbowAngle = angleOf(rightHand2D,
rightElbow2D,
upperArmOrientation);
// show the angles on the screen for debugging
fill(255,0,0);
scale(3);
text("R shoulder: " + int(shoulderAngle) + "\n" +
" elbow: " + int(elbowAngle), 20, 20);
print(int(elbowAngle));
print(": elbow angle");
print(int(shoulderAngle));
println(": shoulder angle");


//////////////////////////////////////////////////////////////////////////////////////////////
PVector leftHand = new PVector();
kinect.getJointPositionSkeleton(userId,
SimpleOpenNI.SKEL_LEFT_HAND,
leftHand);/////////////
PVector leftElbow = new PVector();
kinect.getJointPositionSkeleton(userId,
SimpleOpenNI.SKEL_LEFT_ELBOW,
leftElbow);
PVector leftShoulder = new PVector();
kinect.getJointPositionSkeleton(userId,
SimpleOpenNI.SKEL_LEFT_SHOULDER,
leftShoulder);
// we need right hip to orient the shoulder angle
PVector leftHip = new PVector();
kinect.getJointPositionSkeleton(userId,
SimpleOpenNI.SKEL_LEFT_HIP,
leftHip);
// reduce our joint vectors to two dimensions
PVector leftHand2D = new PVector(leftHand.x, leftHand.y);
PVector leftElbow2D = new PVector(leftElbow.x, leftElbow.y);
PVector leftShoulder2D = new PVector(leftShoulder.x,
leftShoulder.y);
PVector leftHip2D = new PVector(leftHip.x, leftHip.y);
// calculate the axes against which we want to measure our angles
PVector torsoOrientation1 =
PVector.sub(leftShoulder2D, leftHip2D);
PVector upperArmOrientation1 =
PVector.sub(leftElbow2D, leftShoulder2D);
// calculate the angles between our joints
float shoulderAngle1 = angleOf(leftElbow2D,
leftShoulder2D,
torsoOrientation1);
float elbowAngle1 = angleOf(leftHand2D,
leftElbow2D,
upperArmOrientation1);
// show the angles on the screen for debugging
fill(255,0,0);
scale(1);
text("L shoulder: " + int(shoulderAngle1) + "\n" +
" elbow: " + int(elbowAngle1), 120, 20);
print(int(elbowAngle));
print(": elbow angle");
print(int(shoulderAngle));
println(": shoulder angle");
print(int(elbowAngle1));
print(": elbow angle");
print(int(shoulderAngle1));
println(": shoulder angle");
//println(int(shoulderAngle));

byte out[] = new byte[4];
out[0] = byte(int(shoulderAngle));
out[1] = byte(int(elbowAngle));
out[2] = byte(int(shoulderAngle1));
out[3] = byte(int(elbowAngle1));
port.write(out);
}
}


}
float angleOf(PVector one, PVector two, PVector axis) {
PVector limb = PVector.sub(two, one);
return degrees(PVector.angleBetween(limb, axis));
}
// user-tracking callbacks!
void onNewUser(SimpleOpenNI curContext, int userId) {
println("onNewUser - userId: " + userId);
println("\tstart tracking skeleton");

curContext.startTrackingSkeleton(userId);
}
void drawSkeleton(int userId) {
stroke(0);
strokeWeight(5);
kinect.drawLimb(userId, SimpleOpenNI.SKEL_HEAD, SimpleOpenNI.SKEL_NECK);
kinect.drawLimb(userId, SimpleOpenNI.SKEL_NECK, SimpleOpenNI.SKEL_LEFT_SHOULDER);
kinect.drawLimb(userId, SimpleOpenNI.SKEL_LEFT_SHOULDER, SimpleOpenNI.SKEL_LEFT_ELBOW);
kinect.drawLimb(userId, SimpleOpenNI.SKEL_LEFT_ELBOW, SimpleOpenNI.SKEL_LEFT_HAND);
kinect.drawLimb(userId, SimpleOpenNI.SKEL_NECK, SimpleOpenNI.SKEL_RIGHT_SHOULDER);
kinect.drawLimb(userId, SimpleOpenNI.SKEL_RIGHT_SHOULDER, SimpleOpenNI.SKEL_RIGHT_ELBOW);
kinect.drawLimb(userId, SimpleOpenNI.SKEL_RIGHT_ELBOW, SimpleOpenNI.SKEL_RIGHT_HAND);
kinect.drawLimb(userId, SimpleOpenNI.SKEL_LEFT_SHOULDER, SimpleOpenNI.SKEL_TORSO);
kinect.drawLimb(userId, SimpleOpenNI.SKEL_RIGHT_SHOULDER, SimpleOpenNI.SKEL_TORSO);
kinect.drawLimb(userId, SimpleOpenNI.SKEL_TORSO, SimpleOpenNI.SKEL_LEFT_HIP);
kinect.drawLimb(userId, SimpleOpenNI.SKEL_LEFT_HIP, SimpleOpenNI.SKEL_LEFT_KNEE);
kinect.drawLimb(userId, SimpleOpenNI.SKEL_LEFT_KNEE, SimpleOpenNI.SKEL_LEFT_FOOT);
kinect.drawLimb(userId, SimpleOpenNI.SKEL_TORSO, SimpleOpenNI.SKEL_RIGHT_HIP);
kinect.drawLimb(userId, SimpleOpenNI.SKEL_RIGHT_HIP, SimpleOpenNI.SKEL_RIGHT_KNEE);
kinect.drawLimb(userId, SimpleOpenNI.SKEL_RIGHT_KNEE, SimpleOpenNI.SKEL_RIGHT_FOOT);
kinect.drawLimb(userId, SimpleOpenNI.SKEL_RIGHT_HIP, SimpleOpenNI.SKEL_LEFT_HIP);
noStroke();
fill(100,200, 0);
// drawJoint(userId, SimpleOpenNI.SKEL_HEAD);
// drawJoint(userId, SimpleOpenNI.SKEL_NECK);
// drawJoint(userId, SimpleOpenNI.SKEL_LEFT_SHOULDER);
// drawJoint(userId, SimpleOpenNI.SKEL_LEFT_ELBOW);
// drawJoint(userId, SimpleOpenNI.SKEL_NECK);
// drawJoint(userId, SimpleOpenNI.SKEL_RIGHT_SHOULDER);
// drawJoint(userId, SimpleOpenNI.SKEL_RIGHT_ELBOW);
// drawJoint(userId, SimpleOpenNI.SKEL_TORSO);
// drawJoint(userId, SimpleOpenNI.SKEL_LEFT_HIP);
// drawJoint(userId, SimpleOpenNI.SKEL_LEFT_KNEE);
// drawJoint(userId, SimpleOpenNI.SKEL_RIGHT_HIP);
// drawJoint(userId, SimpleOpenNI.SKEL_LEFT_FOOT);
// drawJoint(userId, SimpleOpenNI.SKEL_RIGHT_KNEE);
// drawJoint(userId, SimpleOpenNI.SKEL_LEFT_HIP);
// drawJoint(userId, SimpleOpenNI.SKEL_RIGHT_FOOT);
// drawJoint(userId, SimpleOpenNI.SKEL_RIGHT_HAND);
// drawJoint(userId, SimpleOpenNI.SKEL_LEFT_HAND);
}
void onLostUser(SimpleOpenNI curContext, int userId)
{
println("onLostUser - userId: " + userId);
}
void onVisibleUser(SimpleOpenNI curContext, int userId)
{
// println("ongle 1" , o);

}

   
L'autre phase c'�tait savoir manipuler ces angles traduites par Processing en mouvement instantan� de 4 servomoteurs (deux bras manipulateurs), Tout simplement en utilisant Arduino et en reliant les 4 servomoteurs en 4 sorties PWM d'arduino de fa�on suivante: 


// Kinect Robot Arduino Program 

#include <Servo.h>
// declare both servos

Servo shoulder;
Servo elbow;
// setup the array of servo positions 2
int nextServo = 0;
int servoAngles[] = {0,0};
void setup() {
// attach servos to their pins 3
shoulder.attach(9);
elbow.attach(10);
Serial.begin(9600);
}
void loop() {
if(Serial.available()){
int servoAngle = Serial.read();
servoAngles[nextServo] = servoAngle;
nextServo++;
if(nextServo > 1){
nextServo = 0;
}
shoulder.write(servoAngles[0]);
elbow.write(servoAngles[1]);
}
}
   

Comme �a se voit au bout du programme, le serial a r�alis� cette tache de lire les angles et la biblioth�que servo.h d'arduino les traduites en mouvement instantan�es.

Voila votre vid�o d�monstratif de fonctionnement:




  
http://letselectronic.blogspot.com/
Done by Houssem and Aymen 

benham.houssem@gmail.com 
aymenlachkem@gmail.com 

   

No comments:

Post a Comment