manually moved camera to observe "snap" problem in fingers fed same coordinates into jme to position camera but look !
wrong unit axis !

I'm starting to understand the "snap" problem and getting clues on how to solve it ... In the interim I like to make tools and utilities that will help me.   Like a camera I can enter in location (x,y,z) and the pan, tilt roll and it will zoom me to the correct place.  I think there is more confusion regarding the xyz vs xzy coordinate system :P


Index joint - first attempt to move will rotate and keep the finger's X axis at 45 degrees .. 
If I move the 2nd and 3rd joint they will do the same - cumulative error is ~135 degrees
I don't know why this  occurs on the fingers and no where else ...

i think the wrists/hands/fingers suffer a bit from the tilt they experienced at some point in design
ahhh .. pretty sure it has to do with the unit normals of the hand cover ..
Below the i01.leftHand.index is connected to i01.leftHand.wrist - wrist is  23 degrees shifted .. I have a feeling that reading the degrees out in 3 dimensions puts it into some sort of normal, and that normal is shifted 23 degrees - so since there are 3 joints (each connected to one another) the error is X 3..
 

 

 

This is with Gael's latest vinmoov2.j3o and a random gesture ... fingers still need work 

 

 

Maybe the alignment of the x axis slightly off ?
MRL current code for index is .. 

      jme.attach("i01.leftHand.index", "i01.leftHand.index", "i01.leftHand.index2", "i01.leftHand.index3");
      jme.setRotation("i01.leftHand.index", "x");
      jme.setRotation("i01.leftHand.index2", "x");
      jme.setRotation("i01.leftHand.index3", "x");
      
      jme.setMapper("i01.leftHand.index", 0, 180, -90, -270);
      jme.setMapper("i01.leftHand.index2", 0, 180, -90, -270);
      jme.setMapper("i01.leftHand.index3", 0, 180, -90, -270);
 

 

 

 

JMonkey virtual InMoov running the balance.py script...
As you can see more work needs to be done .. but on the good side, the arms are always going through its body, and more fingers are under control - although they are bending backwards and with only a single joint ...

 

hairygael

5 years 1 month ago

Some more work!

I have been testing this morning to see if I could manage to set my Blender files with angle "rest" positions.

Currently the Blender files I made for VinMoov positions all parts at 0 angle which puts the robot in the "rest", but this assumes each servo is a 0 "rest", which by default in the InMoov service is not the case.

So I made a test in Blender to set 90 "rest" for rothead instead of 0 before exporting to JMonkey.

And it works!!

Because I do not know how to define which axe (by default Y in MRL ??) is rotating a part of VinMoov, I could only test with rothead.

Another question I have is, does MRL auto rotates parts so that Y is toward top of view?

JMonkey's axis of the scene graph is Y is up, X is left right, and Z is forward back

Each node in JME can have a default axis on which in rotates - the default one is Y

These are the ones I create new defaults :  (it would be all that do not rotate on Y)

      jme.setRotation("i01.head.jaw", "x");
      jme.setRotation("i01.head.rollNeck", "z");
      jme.setRotation("i01.head.neck", "x");
      jme.setRotation("i01.rightArm.bicep", "x");
      jme.setRotation("i01.leftArm.bicep", "x");
      jme.setRotation("i01.rightArm.shoulder", "z");
      jme.setRotation("i01.leftArm.shoulder", "z");
      jme.setRotation("i01.rightArm.omoplate", "z");
      jme.setRotation("i01.leftArm.omoplate", "z");
      
Additionally each node can have a Mapper - these are the current map data ..
 
jme.setMapper("i01.head.neck", 0, 180, -90, 90);
jme.setMapper("i01.head.rollNeck", 0, 180, -90, 90);
jme.setMapper("i01.head.rothead", 0, 180, -90, 90);
jme.setMapper("i01.head.jaw", 0, 180, -10, 170); // is this true ? clipping vs attenuation .. should "not" min/max
jme.setMapper("i01.head.rothead", 0, 180, -90, 90);
jme.setMapper("i01.rightArm.bicep", 0, 180, 0, -180);
jme.setMapper("i01.leftArm.bicep", 0, 180, 0, -180);
jme.setMapper("i01.rightArm.shoulder", 0, 180, -30, 150);
jme.setMapper("i01.leftArm.shoulder", 0, 180, -30, 150); // 124 = 29  & rest = 30
jme.setMapper("i01.rightArm.rotate", 0, 180, 90, 270);      
jme.setMapper("i01.leftArm.rotate", 0, 180, -90, 90);
jme.setMapper("i01.rightArm.omoplate", 0, 180, 0, -180);   
 

 

"BINDING" ...
This is what I call taking one part and attaching it to another.
Initially I ignorantly thought that if you dumped all of inmoovs parts in a folder called i01, I could make all the individual files i01.bicep.j3o, i01.hand.j3o, i01.head.j3o ... etc auto-attach to a new master node i01 and all would be well ..  I got that part working, but of course inmoov is not like this - the heirarchy of things is not like this at all ..    

Specific nodes within the files need to be "bound" with specific nodes in other files.

Head bone connected to the neck bone, neck bone connected to the back bone ....

Instead I had created something that connects all pieces to a single node (more like a star fish)

Fortunately I have a "bind" function which binds two nodes together - but when you do that, JME correctly adds the local transformation (which looks correct when things are unbound) to way too high when the nodes are attached.

Parts were rocketing into the sky !

but with a little vector subtraction, we should be able to fix this ...

 

I currently have a nice method that I hope will satisfy the 3 joint moving from one servo.

In MRL it requires a single line per Servo : 

jme.attach("i01.leftHand.index", "i01.leftHand.indexPhal1", "i01.leftHand.indexPhal2", "i01.leftHand.indexPhal3")

This attaches the index servo to the 3 nodes in the finger.

But I was surprised when the fingers joints flew off his hand like a flock of small birds.  They circle out in space never to land again !

Are the axis way out ?  Should I not be using these nodes ?

I suspect you are not using the correct node.

they are called: i01.rightHand.index,i01.rightHand.index2, i01.rightHand.index3

You have i01.leftHandd.index2 - proably want to change it to i01.leftHand.index2

I changed them all to rotate on their "x" axis - but still it looks very scewed - maybe index3 is a different axis ?

I'm a bit confused on what is going on - when I rotate it, it does a ferris wheel around the hand 

Hello Grog,

These are the mappings I currently got, when running the vinmoov.j3o that I have lastly sent you.

The wrists and fingers are not correct regarding angles. It seems Jmonkey MRL brakes the localRotations which are working in Jmonkey SDK on X axis. This is the reason I didn't do the rest of the hand fingers mappings.

 

jme.setRotation("i01.head.jaw", "x")
jme.setRotation("i01.head.neck", "x")
jme.setRotation("i01.head.rollNeck", "z")
jme.setRotation("i01.head.eyeY", "x")
jme.setRotation("i01.torso.topStom", "z")
jme.setRotation("i01.torso.lowStom", "x")
jme.setRotation("i01.rightArm.bicep", "x")
jme.setRotation("i01.leftArm.bicep", "x")
jme.setRotation("i01.rightArm.shoulder", "x")
jme.setRotation("i01.leftArm.shoulder", "x")
jme.setRotation("i01.rightArm.rotate", "y")
jme.setRotation("i01.leftArm.rotate", "y")
jme.setRotation("i01.rightArm.omoplate", "z")
jme.setRotation("i01.leftArm.omoplate", "z")

jme.setRotation("i01.rightHand.index", "x")
jme.setRotation("i01.rightHand.majeure", "x")

jme.setRotation("i01.leftHand.index", "x")
jme.setRotation("i01.leftHand.majeure", "x")

jme.setMapper("i01.head.jaw", 0, 180, -5, 80)
jme.setMapper("i01.head.neck", 0, 180, -20, 20)
jme.setMapper("i01.head.rollNeck", 0, 180, -30, 30)
jme.setMapper("i01.head.eyeY", 0, 180, 30, 175)
jme.setMapper("i01.rightArm.bicep", 0, 180, 0, -150)
jme.setMapper("i01.leftArm.bicep", 0, 180, 0, -150)

jme.setMapper("i01.rightArm.shoulder", 0, 180, 30, -150)
jme.setMapper("i01.leftArm.shoulder", 0, 180, 30, -150)
jme.setMapper("i01.rightArm.rotate", 0, 180, 80, -80)     
jme.setMapper("i01.leftArm.rotate", 0, 180, -80, 80)
jme.setMapper("i01.rightArm.omoplate", 0, 180, 10, -180)
jme.setMapper("i01.leftArm.omoplate", 0, 180, -10, 180)

jme.setMapper("i01.rightHand.index", 0, 180, 90, -90)
jme.setMapper("i01.rightHand.majeure", 0, 180, 90, -90)
jme.setMapper("i01.rightHand.wrist", 0, 180, -20, 60)

jme.setMapper("i01.leftHand.index", 0, 180, 90, -90)
jme.setMapper("i01.leftHand.majeure", 0, 180, 90, -90)
jme.setMapper("i01.leftHand.wrist", 0, 180, 20, -60)

jme.setMapper("i01.torso.topStom", 0, 180, -30, 30)
jme.setMapper("i01.torso.midStom", 0, 180, 50, 130)
jme.setMapper("i01.torso.lowStom", 0, 180, -30, 30)

 

Starting to use the IK3D service

This was a "reach" for point location 5,5,5  ...
Is it close ?  Dunno .. but a dhlink model went "into" the ik3d service - and published angles came out which matched the servo names ..  the method was "not successful" - i made it publish telemetry anyway ...
omoplate was also -1.32 not really a valid servo input ...

TODO :
1. publish the expected error with the set of angles .. some points we can only reach for and cant touch yet..
2. be able to compare what IK "thinks" the positions are and what jme is displaying ...  we're close to apples and apples here 
3. dynamically change IK "sets" where i can through joystick or keyboard as input "say" it should use the "left" IK DH model or "right" IK DHModel etc .. 
 

 

I added a small box to be the IK Test Point - in theory it should try to take the bicep and point it at the box ...
but the IK3D returns "not success" and points all the joints of the left arm into the same position regardles of where the box is ..

I think the error occurs elsewhere but is less demonstrative because the fingers are at the end of the tree.
To see the error occur on a large part:
-Load vinmoov.j3o
-Move the camera close to the robot
-Move the curser of i01.torso.midStom from only 1 or 2 degree watching closely the robot.
-You should see it jump in a fraction closer to the camera
This is because the  i01.torso.midStom has normaly a preset angle on X of 3.775 which is reset to 0 by JMonkeyMRL
 
The same effect occurs on the i01.leftArm.shoulder and i01.rightArm.shoulder on a very small scale barely visible.
The i01.leftHand.wrist and i01.rightHand.wrist have a preset angle on X of 23.822 which also gets reset to 0 by JMonkey.
 
So for the fingers it is the same and I would guess the thumb is going to go wild.
:)
 
I really can't seem to fix this in Blender because it works fine in JMonkey SDK
 
Currently we are lucky almost all the joints of vinmoov are aligned on a Y or Z or X like in the exemple below, without shifted angles:
 
But the hands are aligned with a preset shifted angle like this:
 
 
At the moment this joint is moved in JMonkeyMRL this happens, X gets reset to 0:
 
 
 

Hi Gael,
yep, I did the i01.torso.midStom experiment - and it behaves just like the fingers..
They "snap" into place at the beginning of their first move.  Unfortunately, the "snap" is not the way it was originally imported.
The process of moving things begins by finding the matching name node, reading its local rotation values out, modifying the desired axis of rotation, then writing the values back into the node.
 
Reading values out and writing them back in must occur within or relative to a normal.  So as you were saying, if the normal is re-setting to 0, the values read out and written back in will be "off".
 
It seems to be consistent with what we are observing, and as you put it consistent with being "near correct" for normals which have not been modified.
 
I'm curious as when you say it "works" in JMonkeySDK .. does it work when it's moved or just when its originally imported ?   I'm guessing you are using the rotation tool in JMonkey on the node which matches the servo name, and rotating in in JMonkey-SDK and everything looks correct?  (Because the initial model loaded in MRL looks correct - its just when moving things go bad)

As I mentioned before - I have problems running JMonkey-sdk on my main computer, because of driver conflicts.  But, after loading it on another computer, I can use the rotation tool in JMonkey-sdk and see that it rotates correctly.  There is no "jump/snap" to the 0 base normal, even using the correctly named node.

So .. I got to figure out what I'm doing incorrectly...

 

Hello Greg,

I am glad you have been able to reproduce the snap issue.

It was not easy to explain the scenario. As you see the SDK is doing the movements just fine.

I also wonder what can be the difference between the SDK and MRL.

 

Playing with VinMoov and testng the gestures in JmonkeyMRL, I suddenly saw VinMoov fly off the grid.

Lovely perspective for a robot!

Hi Gael,

Kevin and I were wondering if you have armatures/bones currently defined in master blender files ?  And/Or if you had interest in creating them or trying to export them.

I know that JMonkey has some utility for importing them..

Kevin is now looking into a IK library called (https://github.com/FedUni/caliko)
It looks potentially very promising. (https://www.youtube.com/watch?v=wEtp4P2ucYk)

 
I too at some point will be looking into IK from inside JMonkey which was implemented at the core by the bullet/jbullet library http://jbullet.advel.cz/ with various wrappers ...
 
Any thought or experiences with blender bones ?

hairygael

5 years 1 month ago

In reply to by GroG

Hello Greg,
 
Currently I do not have a bone armature in Blender VinMoov. I am not very familiar with bone because I have no usage for it.
Some years ago I had to design for a job a dwarf which would be 3D printed in many positions and would also be animated in post-production.
I had created a bone armature for the purpose and learned via tutorials how to do it, but I honestly completely forgot the methods.
 
I certainly could look into it and make something for VinMoov. In fact I was wondering since the beginning why bone armature was not used in JMonkeyMRL.
In most game engines it is the default way for animating puppets. But I think it will be a completely another approach than the angles we have been working on lately.
The VinMoov done by Gareth in Blender was using bone armature.
Note that the positions were not correct on Gareth model regarding the hands.

If you want to have a test I attached Gareth's file.

VirtualInMoov.blend

I certainly could look into it and make something for VinMoov. In fact I was wondering since the beginning why bone armature was not used in JMonkeyMRL.

MRL's directive is not to be a cool 3d game (although .. with mrl-jme that might be a great after-affect :)
In game engines often IK which is all mathmatics based often is integrated very tightly with the gui/display/scene-graph.  If we want the same IK to drive a "real" robot, sometimes its impracticle or unfeasable to utilise the game engines IK. Because from the perspective of the 3d game, it was only meant to update some pixels on a screen.

In our system, we need IK extremely modular - so that we can drive real servos, real motors,  and/or simulators.   These are not typical design considerations in 3d game engines.

I'm looking into the details of JMonkey. In my opinion its written very well and seems fairly modular, but I'm still uncertain it will provide us a modular enough IK for our purposes.  (as Alessandro and I often chanted "MRL is Not the GUI" :)

Initially we were using DHParameters, but Kevin found what might be an excellent fit with https://github.com/FedUni/caliko.  And there is also jbullet (for which JMonkeyEngine uses with several wrappers) ... So many choices .. so little time.

When it comes down to it all IK systems need a "skeleton" based on configuration and measurements.  
At the moment MRL-JME uses the scene graph and Mapper configuration for the "skeleton".
It could use "bones" which is more configuration & measurements applied on top of the scene graph..

I'd say its still worth it in the long run to define these things at the source and let down stream applications attempt to utilize them.  But for me its not the highest priority.  Not sure what Kevin feels - he'll have to work at getting caliko calibrated .. perhaps bones would make it easier ..

I suspect he's getting most of his measurements from the current ones in DHParameters ...

Hope this clears some of mystery up ...