Skip to content

Commit

Permalink
Add hgplvm software.
Browse files Browse the repository at this point in the history
  • Loading branch information
Neil Lawrence committed Mar 16, 2015
1 parent 0e55437 commit 05cc96e
Show file tree
Hide file tree
Showing 61 changed files with 3,153 additions and 1 deletion.
39 changes: 38 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,39 @@
# hgplvm
Hierarchical Gaussian process latent variable model.

## Hierarchical Gaussian Process Latent Variable Model - MATLAB Software

# Hierarchical GP-LVM Software

This page describes examples of how to use the hierarchical Gaussian process latent variable model Software (HGPLVM).

The hierarchical GP-LVM allows you to create hierarchies of Gaussian process models. With the toolbox two hierarchy examples are given below.

### Examples

Two examples of hierarchical models are provided with the code, the first is an example where two interacting subjects are jointly model. Two subjects from the <a href="http://mocap.cs.cmu.edu">CMU Mocap data base</a> approach each other and 'high five'. The hierarchy models the subjects separately and jointly. It can be run with the command

```matlab
>> demHighFive1
```

A visualisation of the result, including points that have been propagated through the hierarchy is given below.

<center><img src="demHighFive_talk.png"><br>

Joint visualisation of the two subjects that 'high five'. The points A, B, C, D, E, F, G and H have been propagated through the hierarchy and are shown on the right. Grey scale visualisations in the latent space have not been shown to keep the smaller plots clear.</center>

A second example involves a subject modelled running and walking. In this case the separate limbs of the subject are split into a hierarchy as shown below.

<center><img src="stickHierarchy.png"><br>Hierarchical decomposition of the skeleton. The limbs and abdomen are leaf nodes, behind which we build a hierarchical structure.</center>

This example can be reconstructed with
```matlab
>> demWalkRun1
```

Results of applying the hierarchical structure to a combined data set of a run and a walk, using two root nodes, one for the run and one for the walk, are shown below.

<center><img src="demWalkRun_portrait.png"><br>
Visualisation of a walk and run jointly using hierarchical structures. Again several points have been propagated through the hierarchy.
</center>

141 changes: 141 additions & 0 deletions matlab/acclaim2xyzHierarchical.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
function xyz = acclaim2xyzHierarchical(skel, channels, visIndex)

% ACCLAIM2XYZHIERARCHICAL Compute XYZ values given skeleton structure and channels.
% FORMAT
% DESC Converts a series of joint angles (channel data) into xyz
% coordinates for the given skeleton.
% ARG skel : The skeleton being animated.
% ARG channels : The channel data for this frame of animation.
% ARG visIndex : visIndex indicates the index of the current subskel node.
% RETURN xyz : the data structure containing the xyz value and rotation
% matrix for each joint in the skeleton.
%
% COPYRIGHT : Andrew J. Moore and Neil D. Lawrence, 2006, 2007
%
% HGPLVM

global dependencyVisData;

%/~
% hasDependency = 0;
% isMaster = 0;
% dependencyId = 0;
% %check to see if root node has a dependency.
% for i=1:size(dependencyVisData)
% if (strcmp(skel.tree(1).name, dependencyVisData(i).name)
% %check to see if this is a master or a dependent.
% if dependencyVisData(i).masterNodeIndex == visIndex
% isMaster = 1;
% dependencyId = i;
% else
% xyzStruct(1).rot = dependencyVisData(i).rot;
% xyzStruct(1).xyz = dependencyVisData(i).xyz;
% hasDependency = 1;
% end
% end
% end
% if ~hasDependency
%~/
rotVal = skel.tree(1).orientation;
for i = 1:length(skel.tree(1).rotInd)
rind = skel.tree(1).rotInd(i);
if rind
rotVal(i) = rotVal(i) + channels(rind);
end
end
xyzStruct(1).rot = rotationMatrix(deg2rad(rotVal(1)), ...
deg2rad(rotVal(2)), ...
deg2rad(rotVal(3)), ...
skel.tree(1).axisOrder);

xyzStruct(1).xyz = skel.tree(1).offset;
%/~
% end
%~/

for i = 1:length(skel.tree(1).posInd)
pind = skel.tree(1).posInd(i);
if pind
xyzStruct(1).xyz(i) = xyzStruct(1).xyz(i) + channels(pind);
end
end
xyzStruct(1) = checkForDependency(1, visIndex, xyzStruct(1));


for i = 1:length(skel.tree(1).children)
ind = skel.tree(1).children(i);
xyzStruct = getChildXyz(skel, xyzStruct, ind, channels);
end
xyz = reshape([xyzStruct(:).xyz], 3, length(skel.tree))';

function xyzStruct = getChildXyz(skel, xyzStruct, ind, channels)

% GETCHILDXYZ

parent = skel.tree(ind).parent;
children = skel.tree(ind).children;
rotVal = zeros(1, 3);
for j = 1:length(skel.tree(ind).rotInd)
rind = skel.tree(ind).rotInd(j);
if rind
rotVal(j) = channels(rind);
else
rotVal(j) = 0;
end
end
tdof = rotationMatrix(deg2rad(rotVal(1)), ...
deg2rad(rotVal(2)), ...
deg2rad(rotVal(3)), ...
skel.tree(ind).order);

torient = rotationMatrix(deg2rad(skel.tree(ind).axis(1)), ...
deg2rad(skel.tree(ind).axis(2)), ...
deg2rad(skel.tree(ind).axis(3)), ...
skel.tree(ind).axisOrder);
torientInv = rotationMatrix(deg2rad(-skel.tree(ind).axis(1)), ...
deg2rad(-skel.tree(ind).axis(2)), ...
deg2rad(-skel.tree(ind).axis(3)), ...
skel.tree(ind).axisOrder(end:-1:1));
xyzStruct(ind).rot = torientInv*tdof*torient*xyzStruct(parent).rot;
xyzStruct(ind).xyz = xyzStruct(parent).xyz + (skel.tree(ind).offset*xyzStruct(ind).rot);

xyzStruct(ind) = checkForDependency(ind, visIndex, xyzStruct(ind));

for n = 1:length(children)
cind = children(n);
xyzStruct = getChildXyz(skel, xyzStruct, cind, channels);
end

end

function xyzStruct = checkForDependency(ind, visIndex, xyzStruct)

% CHECKFORDEPENDENCY

%/~
%below prob shite
%0 = no dependency
%1 = dependency, is dependent
%2 = dependency, is master
%~/
for k=1:length(dependencyVisData)
if (strcmp(skel.tree(ind).name, dependencyVisData(k).name))
%check to see if this is a master or a dependent.
if dependencyVisData(k).masterNodeIndex == visIndex
% It is master.
dependencyVisData(k).rot = xyzStruct.rot;
dependencyVisData(k).xyz = xyzStruct.xyz;
else
%hot fix, but question is, why might the dependency master info be
%requested before is has been assigned?
if ~isempty(dependencyVisData(k).rot)
% It is a dependent
xyzStruct.rot = dependencyVisData(k).rot;
xyzStruct.xyz = dependencyVisData(k).xyz;
end
end
end
end
end

end
185 changes: 185 additions & 0 deletions matlab/acclaimGetSubSkel.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
function [subskel, channelIndices] = acclaimGetSubSkel(skel, newRootName, children, stoplist)

% ACCLAIMGETSUBSKEL Gets a sub-skeleton from a larger acclaim format skeleton.
% FORMAT
% DESC gets a sub-skeleton from a larger skeleton given the
% original skeleton, the root of the new skeleton and the joints
% from the root to be included in the sub-skeleton.
% ARG skel : Original skeleton to take a subskel from.
% ARG newRootName : Name of the joint from skel which will be the
% root of the new subskel.
% ARG children : Cell array containing the names of joints/bones
% below newRootName which are to be included in the subskel (omitting this will add all children of newRootName).
% ARG stoplist : Cell array containing the names of joints/bones. If any
% joint is explored which has a name on the stoplist, then this
% joint and its child joints are not added to the new subskel.
% RETURN subkel : the sub-skeleton as specificed by the given
% arguments.
% RETURN channelIndices : the relevant channel indices associated with the
% sub-skeleton.
%
% COPYRIGHT : Andrew J. Moore and Neil D. Lawrence, 2006, 2007
%
% SEEALSO : skelReverseLookup

% HGPLVM

%/~
% Andy, this is based on your skelGetSubSkel -- Neil
%~/
IND_ROOT = 1; %assume the index of a root node is always 1.

if nargout>1
getSubChannels = 1;
channelIndices = [];
else
getSubChannels = 0;
end
if nargin < 4
stoplist = {};
elseif ~iscell(stoplist)
error('The ''stoplist'' parameter must be passed as a cell array.');
end
if nargin > 2
if ~iscell(children)
error('The ''children'' parameter must be passed as a cell array.');
end
else
children = {};
end

%Copy over key skel info
subskel.type = skel.type;

jointIndex = skelReverseLookup(skel, newRootName);
newIndex = 1; %global store of the current flat index of the subskel tree array.

%If the children parameter is defined, prune from the skel any child indices not
%in children.
if size(children, 1) > 0
for n=1:length(children)
childJointIndices(n) = skelReverseLookup(skel, children(n));
end
count = 1;
for m=1:length(skel.tree(jointIndex).children)
bJointMatch = 0;
for n=1:length(childJointIndices)
if childJointIndices(n) == skel.tree(jointIndex).children(m)
bJointMatch = 1;
end
end
if bJointMatch
prunedChildren(count) = skel.tree(jointIndex).children(m);
count = count + 1;
end
end
skel.tree(jointIndex).children = prunedChildren;
end

%if the root of the subskel is not the root of the original skel, need to
%calculate the position offset of the new subskel from the original root
if not(strcmp(newRootName,'root'))
%calculate the cumulative offset of the root of the subskel from the
%original skel root.
rootOffset = skel.tree(jointIndex).offset;
%BEGIN - calculate the offset in relation to the whole skel. should now
%be done at run time -
%nodeIndex = skel.tree(jointIndex).parent;
%while nodeIndex > 0
% rootOffset = rootOffset + skel.tree(nodeIndex).offset;
% nodeIndex = skel.tree(nodeIndex).parent;
%end
%END
subskel.tree(IND_ROOT) = skel.tree(jointIndex);
subskel.tree(IND_ROOT).offset = rootOffset;
subskel.tree(IND_ROOT).orientation = skel.tree(IND_ROOT).orientation;
%need to add in the posInd (x,y,z), setting to the original roots value
subskel.tree(IND_ROOT).posInd = skel.tree(IND_ROOT).posInd;
else
subskel.tree(IND_ROOT) = skel.tree(IND_ROOT);
end
%copy over position data from orig skel root to the new subskel root
if getSubChannels
channelIndices = [channelIndices 1:3];
nextChanIndex = 4;
end


%Note that the rotation indices attribute, rotInd, of each bone contains
%the indices of the channel data for each DoF.

recurseTree(jointIndex, 0, true); %set parent index to the orig skel root.

function z = recurseTree(skelIndex, subskelParentIndex, continueRecursion)
%skelIndex - index in skel of the current node to copy.
%subskelParentIndex - the index in subskel of this node's parent.
if nargin < 3
continueRecursion = true;
end
thisNodeIndex = newIndex;

%need to re calculate the parent and child indices
if subskelParentIndex > 0
subskel.tree(thisNodeIndex) = skel.tree(skelIndex);
subskel.tree(thisNodeIndex).parent = subskelParentIndex; % re-set this node's parent
end
if getSubChannels
%copy the old channel data over, and update the rotInd's to the
%new positions in the subchannels matrix.
for i = 1:length(subskel.tree(thisNodeIndex).rotInd)
if subskel.tree(thisNodeIndex).rotInd(i)
channelIndices = [channelIndices subskel.tree(thisNodeIndex).rotInd(i)];
subskel.tree(thisNodeIndex).rotInd(i) = nextChanIndex;
nextChanIndex = nextChanIndex + 1;
end
end
end

newIndex = newIndex + 1;
numChildren = length(skel.tree(skelIndex).children);
unblockedChildCounter = 1;
%clear the current children copied from subskel, and recalulate the
%new child indicies
subskel.tree(thisNodeIndex).children = [];
% if continueRecursion if false, recurse through the children.
if continueRecursion
for i = 1:numChildren
childSkelIndex = skel.tree(skelIndex).children(i);
if inStoplist(skel.tree(childSkelIndex).name)
% Find children, but don't recurse through them.
recurseFurther = false;
else
recurseFurther = true;
end
childSubskelIndex = recurseTree(childSkelIndex, ...
thisNodeIndex, ...
recurseFurther);
subskel.tree(thisNodeIndex).children(unblockedChildCounter) = ...
childSubskelIndex;
unblockedChildCounter = unblockedChildCounter + 1;
end
end
z = thisNodeIndex; %return the id of this node, used for setting child id's on parent.
end

%function inStoplist
%newRootName - the name of a joint
%Returns 0 or 1 to indicate if jointName is in the stoplist
function result = inStoplist(jointName)
result = false;
for i = 1:length(stoplist)
if strcmp(jointName, stoplist(i))
result = true;
return;
end
end

end

end






Loading

0 comments on commit 05cc96e

Please sign in to comment.