Skip to content

Instantly share code, notes, and snippets.

@error454
Last active December 20, 2015 22:49
Show Gist options
  • Save error454/6208404 to your computer and use it in GitHub Desktop.
Save error454/6208404 to your computer and use it in GitHub Desktop.
Leap joints etc for Payam.

leapFrame.js defines a function that helps you read and act on a single frame of leap data.
The leap device passes 'frames' of data as it sees objects in the world. A single frame of data has information on how many objects are seen, what direction they're pointing, where they're located in 3D space etc. Take time and look at leapFrame.js and the functions it provides:

  • palm position
  • palm direction
  • palm normal vector
  • finger position
  • finger angle
  • delta finger position

If you need some help figuring out what some of these vectors look like, take a look at the leap documentation, they have nice pictures showing all the axis etc.

joint.js defines a function that helps create and move joints. In the sample code sent me, you see a joint constructed like this:

var middle = new Joint({
  minPos: 70,
  maxPos: 220,
  pin: 6,
  range: [60,150]
});

The range is quite important, this is where you specify the range of motion in degrees of the servo. The servo above is being set to 60 degrees minimum, 150 degrees maximum.

minPos, maxPos - These define the minimum and maximum value for the leap property that is being used to move this servo. For instance, in the code above, you can see the minPos and maxPos values being set to 70 and 220. 70 and 220 are values you'll be getting from the leap device for whatever part/property of the hand you choose. In the example, the palm's height is being used:

middle.move(frame.palmPosition.y);

Remember that middle is a Joint, and here you see that from the frame data, the palmPosition Y value is being passed to the joint move function. What happens to the value passed into middle.move?

var _move = function(pos, constraint) {
  var angle;
	if (constraint) {
		pos = constraint(pos);
	}
	angle = _scale(pos);
	_servo.move(angle);
};

You can see that without a second argument, the call to move basically just calls scale(pos) and stores the value.

Let's see what scale does:

var _scale = function(pos) {
    if (pos<minPos) {
    	pos = minPos;
    }
    else if (pos>maxPos) {
    	pos = maxPos;
    }
    return Math.floor(five.Fn.map(pos, minPos, maxPos, _servo.range[0], _servo.range[1]));
};

This function clamps the position passed in to the minPos and maxPos values that were defined when constructing the joint. It then interpolates the value across the min/max servo range.

@error454
Copy link
Author

The code you sent me is definitely using pointables and not fingers. Every frame, the leap device returns everything it saw:

  • Tools are things like chopsticks or anything that's long and skinny but that may not be a finger.
  • Fingers are... fingers
  • Pointables include tools and fingers

You can use the direction vector of the pointables to determine how much they are bent (http://leapmotion.github.io/leapjs/Leap.Pointable.html). For instance you might want to take the cross product of the direction vector with a vector pointing straight down and see how close to zero the magnitude is (zero means the vectors are parallel).

_isValid is called every time app.js calls frame = new LeapFrame(data);, and changing it to frame.hand won't do what you want. Frame is this (http://leapmotion.github.io/leapjs/Leap.Frame.html#Frame) look at the data structures in there and you'll see where frame.pointables and frame.hands come from.

Unfortunately the code you sent only tracks a single pointable. You'd need to make some changes to track more than a single pointable. Also, if you want to map a specific finger to a specific control then you will probably need some type of calibration phase where you can identify a single finger at a time and store the ID of that finger...

Otherwise you might have 5 fingers on screen, then you might lose site of 1 finger and your finger enumerations will change. So what you thought was the pinky may now be in index 3 instead of index 4.

@payam1995
Copy link

any way to track my entire hand (wrist onwards, i don't mean the arm)? i mean move a servo with respect to my palm radius? that'd be a good alternative if i be facing too many problems tracking multiple fingers. Any way to bring my whole hand into account? (not just a finger) if yes can you please tell me how...

i just want it detect my hand (not just my one finger) somehow, i just don't know where to begin.

@error454
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment