Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rotation axis #198

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions examples/threejs-bones.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
</body>

<script>
// note: before implementing based off of this, you can instead grab the boneHand plugin
// here: js.leapmotion.com

var colors = [0xff0000, 0x00ff00, 0x0000ff];
var baseBoneRotation = (new THREE.Quaternion).setFromEuler(
new THREE.Euler(Math.PI / 2, 0, 0)
Expand Down
70 changes: 53 additions & 17 deletions leap-0.6.3.js
Original file line number Diff line number Diff line change
Expand Up @@ -1836,14 +1836,25 @@ Frame.prototype.hand = function(id) {
Frame.prototype.rotationAngle = function(sinceFrame, axis) {
if (!this.valid || !sinceFrame.valid) return 0.0;

// A derivation of the following can be found here:
// http://en.wikipedia.org/wiki/Axis–angle_representation
var rot = this.rotationMatrix(sinceFrame);
var cs = (rot[0] + rot[4] + rot[8] - 1.0)*0.5;
var angle = Math.acos(cs);

var axis = [
rot[7] - rot[5],
rot[2] - rot[6],
rot[3] - rot[1]
];

var sin = Leap.vec3.len(axis);
var cos = (rot[0] + rot[4] + rot[8] - 1.0) * 0.5;

var angle;
angle = Math.atan2(sin,cos);
angle = isNaN(angle) ? 0.0 : angle;

if (axis !== undefined) {
var rotAxis = this.rotationAxis(sinceFrame);
angle *= vec3.dot(rotAxis, vec3.normalize(vec3.create(), axis));
angle *= vec3.dot(sin, vec3.normalize(vec3.create(), axis));
}

return angle;
Expand All @@ -1854,6 +1865,9 @@ Frame.prototype.rotationAngle = function(sinceFrame, axis) {
* the current frame and the specified frame.
*
* The returned direction vector is normalized.
*
* In the case of a complete reversal of direction (180 deg / PI rad)
* this method will return an undefined axis.
*
* The Leap derives frame rotation from the relative change in position and
* orientation of all objects detected in the field of view.
Expand All @@ -1869,10 +1883,14 @@ Frame.prototype.rotationAngle = function(sinceFrame, axis) {
*/
Frame.prototype.rotationAxis = function(sinceFrame) {
if (!this.valid || !sinceFrame.valid) return vec3.create();

var rotation = Leap.mat3.create();
Leap.mat3.multiply(rotation, this._rotation, sinceFrame._rotation);

return vec3.normalize(vec3.create(), [
this._rotation[7] - sinceFrame._rotation[5],
this._rotation[2] - sinceFrame._rotation[6],
this._rotation[3] - sinceFrame._rotation[1]
rotation[7] - rotation[5],
rotation[2] - rotation[6],
rotation[3] - rotation[1]
]);
}

Expand Down Expand Up @@ -2754,15 +2772,29 @@ Hand.prototype.rotationAngle = function(sinceFrame, axis) {
var sinceHand = sinceFrame.hand(this.id);
if(!sinceHand.valid) return 0.0;
var rot = this.rotationMatrix(sinceFrame);
var cs = (rot[0] + rot[4] + rot[8] - 1.0)*0.5
var angle = Math.acos(cs);
angle = isNaN(angle) ? 0.0 : angle;

var axis = [
rot[7] - rot[5],
rot[2] - rot[6],
rot[3] - rot[1]
];

var sin = Leap.vec3.len(axis);
var cos = (rot[0] + rot[4] + rot[8] - 1.0) * 0.5;

var angle;
if (-1e-7 < sin && sin < 1e-7) { // small values of sin
angle = 0;
} else {
angle = Math.atan2(sin,cos);
angle = isNaN(angle) ? 0.0 : angle;
}

if (axis !== undefined) {
var rotAxis = this.rotationAxis(sinceFrame);
angle *= vec3.dot(rotAxis, vec3.normalize(vec3.create(), axis));
angle *= vec3.dot(sin, vec3.normalize(vec3.create(), axis));
}
return angle;
}
};

/**
* The axis of rotation derived from the change in orientation of this hand, and
Expand All @@ -2783,12 +2815,16 @@ Hand.prototype.rotationAxis = function(sinceFrame) {
if (!this.valid || !sinceFrame.valid) return vec3.create();
var sinceHand = sinceFrame.hand(this.id);
if (!sinceHand.valid) return vec3.create();

var rotation = Leap.mat3.create();
Leap.mat3.multiply(rotation, this._rotation, sinceHand._rotation);

return vec3.normalize(vec3.create(), [
this._rotation[7] - sinceHand._rotation[5],
this._rotation[2] - sinceHand._rotation[6],
this._rotation[3] - sinceHand._rotation[1]
rotation[7] - rotation[5],
rotation[2] - rotation[6],
rotation[3] - rotation[1]
]);
}
};

/**
* The transform matrix expressing the rotation derived from the change in
Expand Down
6 changes: 3 additions & 3 deletions leap-0.6.3.min.js

Large diffs are not rendered by default.

32 changes: 25 additions & 7 deletions lib/frame.js
Original file line number Diff line number Diff line change
Expand Up @@ -318,14 +318,25 @@ Frame.prototype.hand = function(id) {
Frame.prototype.rotationAngle = function(sinceFrame, axis) {
if (!this.valid || !sinceFrame.valid) return 0.0;

// A derivation of the following can be found here:
// http://en.wikipedia.org/wiki/Axis–angle_representation
var rot = this.rotationMatrix(sinceFrame);
var cs = (rot[0] + rot[4] + rot[8] - 1.0)*0.5;
var angle = Math.acos(cs);

var axis = [
rot[7] - rot[5],
rot[2] - rot[6],
rot[3] - rot[1]
];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A reasonably clear derivation can be found here: http://en.wikipedia.org/wiki/Axis–angle_representation#Exponential_map_from_so.283.29_to_SO.283.29

Also see the log map section.

var sin = Leap.vec3.len(axis);
var cos = (rot[0] + rot[4] + rot[8] - 1.0) * 0.5;

var angle;
angle = Math.atan2(sin,cos);
angle = isNaN(angle) ? 0.0 : angle;

if (axis !== undefined) {
var rotAxis = this.rotationAxis(sinceFrame);
angle *= vec3.dot(rotAxis, vec3.normalize(vec3.create(), axis));
angle *= vec3.dot(sin, vec3.normalize(vec3.create(), axis));
}

return angle;
Expand All @@ -336,6 +347,9 @@ Frame.prototype.rotationAngle = function(sinceFrame, axis) {
* the current frame and the specified frame.
*
* The returned direction vector is normalized.
*
* In the case of a complete reversal of direction (180 deg / PI rad)
* this method will return an undefined axis.
*
* The Leap derives frame rotation from the relative change in position and
* orientation of all objects detected in the field of view.
Expand All @@ -351,10 +365,14 @@ Frame.prototype.rotationAngle = function(sinceFrame, axis) {
*/
Frame.prototype.rotationAxis = function(sinceFrame) {
if (!this.valid || !sinceFrame.valid) return vec3.create();

var rotation = Leap.mat3.create();
Leap.mat3.multiply(rotation, this._rotation, sinceFrame._rotation);

return vec3.normalize(vec3.create(), [
this._rotation[7] - sinceFrame._rotation[5],
this._rotation[2] - sinceFrame._rotation[6],
this._rotation[3] - sinceFrame._rotation[1]
rotation[7] - rotation[5],
rotation[2] - rotation[6],
rotation[3] - rotation[1]
]);
}

Expand Down
38 changes: 28 additions & 10 deletions lib/hand.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,15 +246,29 @@ Hand.prototype.rotationAngle = function(sinceFrame, axis) {
var sinceHand = sinceFrame.hand(this.id);
if(!sinceHand.valid) return 0.0;
var rot = this.rotationMatrix(sinceFrame);
var cs = (rot[0] + rot[4] + rot[8] - 1.0)*0.5
var angle = Math.acos(cs);
angle = isNaN(angle) ? 0.0 : angle;

var axis = [
rot[7] - rot[5],
rot[2] - rot[6],
rot[3] - rot[1]
];

var sin = Leap.vec3.len(axis);
var cos = (rot[0] + rot[4] + rot[8] - 1.0) * 0.5;

var angle;
if (-1e-7 < sin && sin < 1e-7) { // small values of sin
angle = 0;
} else {
angle = Math.atan2(sin,cos);
angle = isNaN(angle) ? 0.0 : angle;
}

if (axis !== undefined) {
var rotAxis = this.rotationAxis(sinceFrame);
angle *= vec3.dot(rotAxis, vec3.normalize(vec3.create(), axis));
angle *= vec3.dot(sin, vec3.normalize(vec3.create(), axis));
}
return angle;
}
};

/**
* The axis of rotation derived from the change in orientation of this hand, and
Expand All @@ -275,12 +289,16 @@ Hand.prototype.rotationAxis = function(sinceFrame) {
if (!this.valid || !sinceFrame.valid) return vec3.create();
var sinceHand = sinceFrame.hand(this.id);
if (!sinceHand.valid) return vec3.create();

var rotation = Leap.mat3.create();
Leap.mat3.multiply(rotation, this._rotation, sinceHand._rotation);

return vec3.normalize(vec3.create(), [
this._rotation[7] - sinceHand._rotation[5],
this._rotation[2] - sinceHand._rotation[6],
this._rotation[3] - sinceHand._rotation[1]
rotation[7] - rotation[5],
rotation[2] - rotation[6],
rotation[3] - rotation[1]
]);
}
};

/**
* The transform matrix expressing the rotation derived from the change in
Expand Down