Table of Contents

Gaussian Process Latent Variable Model (GPLVM)

Principe

L'idée d'un GPLVM est d'apprendre un espace latent de faible dimension qui permet de représenter des données de plus haute dimensions par l'intermédiaire de processus gaussiens dont les paramètres sont appris. Dans notre cas, nous voulons utiliser ces modèles pour l'imitation du mouvement humain par un robot. Pour cela, un même modèle sera partagé entre les données humains et les données robot. Ainsi, l'espace latent sert de mapping intermédiaire entre l'espace humain et l'espace robot. Plus d'information théorique peut être trouvée dans les papiers suivants:

Code

Le code s'appuie fortement sur celui développé par Lawrence, N. D. disponible sur github: https://github.com/lawrennd/sgplvm Afin d'utiliser les dépendances nécessaires, exécutez tout d'abord le script paths.m Ensuite le code principal se trouve dans le script main.m

La démonstration a pour but de charger un mouvement humain et son mouvement Poppy correspondant.

%% Loading training data%%
% load Poppy data: angles are in Z_train
[Z_train_ori] = readPoppyExoData('cacheTeteKine');
nbData = size(Z_train_ori,1); %length of the sequence
 
% load Skeleton data: orientation are in O_train, position in Y_train.
% O_train is not used
dirTrain='data\skeleton\'; %Directory of skeleton data
fnameTrain='SkeletonSequence0.txt'; %Filename of skeleton data
[O_train,Y_train,dataTrain] = loadData(dirTrain,fnameTrain,0,0,1,21,nbData);
O_train=O_train';Y_train=Y_train';

Les données d'angles Poppy sont chargées à partir des fichiers exercices au format json créés via l'application web Poppy GRR Keraal. Un fichier exercice contient la liste des mouvements contenus dans l'exercice. Un fichier mouvement, également au format json, contient la liste des positions en angles de chaque moteur pour chaque timestamp du mouvement. Ainsi la fonction 'readPoppyExoData' récupère ces angles dans une matrice où chaque ligne est une trame et les angles sont en colonne dans l'ordre des ids des moteurs de Poppy.

Les données de squelette humain incluent pour chaque articulation la position (coordonnées carthésiennes en 3 dimensions) et l'orientation (sous forme de quaternion). Les fichiers de mouvement ont été enregistrés à l'aide de la bibliothèque Kinect. Ainsi la fonction 'loadData' retourne la matrice des orientations, la matrice des positions, et une structure contenant les données pour chaque articulation séparément. Le format des matrices est une ligne par trame, et les données en colonnes sont dans l'ordre de la hiérarchie du squelette.

L'alignement temporel entre les deux séquences peut être nécessaire pour s'assurer des correspondances entre les données de squelette humain et les données du robot Poppy.

registration=1; %make temporal alignment or not
if registration==1
    [Z_train,Y_train] = temporalAlignment(Z_train_ori,Y_train);
end

De plus, les données de positions du squelettes sont dans Y_train et les angles moteurs sont dans Z_train. Dans la démo, uniquement les données du bras gauche sont utilisées. Comme chaque partie du corps peut être indépendant des autres, il est conseillé de les considérer séparément comme dans la démo.

%Keep only the left arm
Y_trainLA=Y_train(:,13:24);
Z_trainLA=Z_train(:,8:11);

Le but est d'apprendre un modèle partagé entre les deux espaces et donc un mapping entre les deux espaces. Le paramètre nbIters définit le nombre maximal d'itérations de l'algorithme d'optimisation du modèle.

%% Learning GPLVM
nbIters=2000; %Number of iterations for the learning algorithm
model = learningGPLVM2D(Z_trainLA,Y_trainLA, nbIters);
</code
 
    * 3. Évaluation et affichage
Une fois le modèle appris, le but est d'imiter un mouvement humain. Pour cela on charge une nouvelle séquence humain et l'on génère la séquence d'angles Poppy correspondante. 
<code matlab>
%% Evaluate a sequence
fnameTest='SkeletonSequence1.txt'; %Filename of skeleton data
[O_test,Y_test,dataTest] = loadData(dirTrain,fnameTest,0,0,1,21,nbData); %load test skeleton sequence
O_test=O_test';Y_test=Y_test';
[Z_train2,Y_test] = temporalAlignment(Z_train_ori,Y_test); %Onlyd needed for comparison purpose
%Keep only the left arm
Y_testLA=Y_test(:,13:24);
 
% Evaluation => corresponding poppy angles are in Z_test
[L_testLA,Z_testLA] = evaluateSkeletonSequence(model,Y_testLA);

La séquence de test étant un mouvement similaire à celui appris, on peut directement afficher les angles estimés (bleu) en comparaison des angles appris (rouge).

% plotting results
subplot(2,2,1),plot(Z_trainLA(:,1),'r');hold on ;plot(Z_testLA(:,1),'b');
subplot(2,2,2),plot(Z_trainLA(:,2),'r');hold on ;plot(Z_testLA(:,2),'b');
subplot(2,2,3),plot(Z_trainLA(:,3),'r');hold on ;plot(Z_testLA(:,3),'b');
subplot(2,2,4),plot(Z_trainLA(:,4),'r');hold on ;plot(Z_testLA(:,4),'b');