Vector normals calculation. Headache ;)


#1

Hi, Just pokng about with this “AR” bringing a hand into Rhino, I bring in the joints as point3d’s from the leap library, then draw the "wires between them, I am trying to bring an object from world origin to a specific finger, using a vector translate, but the “roll” (rotation around Y axis) is quite random and uncontrollable.

I tried three seperate X, Y and Z rotations based on the angles I can pull from the library about the finger XYZ_pitch,roll,yaw, but the Movepitchroll*yaw transform is a tad nuts, ring goes flying all over space.

Vector transform gets me 99% there except that damn roll, any clues on how to work around this?

My current code and some image of the issue, the little ball is Z top.

My current thing is you cant pull a "normal from a vector (i may be wrong) so create a mesh between the two point si do have and the neighbouring two points from the next finger, create a surface/mesh, then pull a normal from that, but how would I apply that normal in my vector equation?

var fingerpointto = (PointsConduit.PointList[15] + PointsConduit.PointList[14]) / 2; //ring finger
var translate = fingerpointto - Point3d.Origin;
var VectorTo = PointsConduit.PointList[15] - PointsConduit.PointList[14];
var Rotation = Transform.Rotation(Vector3d.YAxis, VectorTo, Point3d.Origin);
var Move = Transform.Translation(translate);
var TotalTransform = Move * Rotation;
e.Display.DrawObject(ring, TotalTransform);

Thanks!


(qythium) #2

Try using Transform.PlaneToPlane instead:

var plane0 = Plane(Point3d.Origin, Vector3d.ZAxis, Vector3d.XAxis); 
var plane1 = Plane(fingerPoint, fingerDirection, Vector3d.XAxis)
var xform = Transform.PlaneToPlane(plane0, plane1)

This uses the world X axis as an arbitrary “alignment axis” which may cause some instability (gimbal lock) if your finger is closely aligned with X , you could also use another local reference (e.g. base of thumb) to define the ending plane.


#3

that didnt work either as the “direction vector” that comes back from the api is a quaternion, which can be broken down to x,y,z and w(world I assume). The “normal” is calculate as a floating point from those but there are complications, because first of all you have to swap Z and Y, then *-1 all the values to get them oriented correctly to the hand, which kinda works, except there is a scaling factor difference between the radians in rhinoworld and api world (roughly * 1.96) and that gives me enough to continue the project, but the inversion mean if hand turn upside down, all the x,y,z rotations are flipped and ring faces inside the hand, I can overcome it by detecting palm normal and fis, but it wont fix when they make a fist and the finger is upside down compared to palm still normal up, etc etc etc… ported to blender using some example scripts in python, and the quaternion from api is used directly , no need to dissasemble it to extract seperate axis rotatiosn and normal, and the motion and tracking is perfect, i will pump the whole thing over to that if I cant solve inside rhino.


(Radovan Grmusa) #4

In Rhino (Matrix) you would use _Orient3Pt command to orient solid object in 3D space. And it is actually as proposed before by qythium

Try using Transform.PlaneToPlane instead:



ring_AR.gh (362.7 KB)

Anyway, there is usually more then one way how to get to the solution.


#5

Thanks, way too slow in the conduit, I figured out how to translate the leap quaternion to something that works with rhino so the code to translate and transform is 5 lines long… spend rest of my day finetuning the “offset” that rhino requires on angles from leap (1.967 factor multiplication), and adding a class to do collision detection, as many “buttons” as you like (they just brep bounding boxes in the calculation) and the class will return unique finger tip that touched and which button(s).

Onto pinch-zoom and swipe at moment. Thank for the advice guys.


(qythium) #6

It sounds like there’s a big misunderstanding here about quartenions … they are a completely different way of representing rotations in 3D space, you can’t just take the first three components and treat it as a 3d vector.

I’m not familiar with the library API you are using for Leap controller, but there are usually standard ways of getting a rotation matrix directly from the quartenion representation -
See for example http://developer.rhino3d.com/api/RhinoCommon/html/M_Rhino_Geometry_Quaternion_GetRotation.htm
http://developer.rhino3d.com/api/RhinoCommon/html/M_Rhino_Geometry_Quaternion_MatrixForm.htm

Then just compose it with the translation to the finger position and that should be all.


#7

@Dale!

Awesome, i RTFM on the api for the method, and what I assumed were the radians where actually angular velocity ;), 1 single difference in spelling… in programming syntax is everything ;), handy data to emulate the ring “slipping” on the finger over cetrtain speeds but utterly useless for what I needed it for :wink:

thanks for the help. the plane to plane method above was VERY slow, the degrees extraction faster, but direct use of the correct quaternion is WAY faster, again many thanks.


#8

New Problem,I am flooding the position info to the conduit d\faster than it can handle it, does the conduit set flag to say if its still busy or not?