access armature bones in gameengine python

hi guys, sorry for asking this question, as i am relatively sure it was answered somewhere and i read about it, but google is once again hiding information from me :spin:

is there a possibillity to access bones with python?
for example:

g = GameLogic
c = g.getCurrentController()
o = c.owner

#o is the armature
o.bones["bone name"]

i of course tried to dir() the armature, but it seems that there is no property or function to get the bones?

i found a thread containing a python script which adds bones to a newly created armature:
http://blenderartists.org/forum/showthread.php?t=145934&highlight=armature+bone
but since the script is importing blender and uses makeEditable() i do not think that this will work in the gameengine=?

thanks a lot for reading this,
even more thanks if you bother to answer,

greetings from vienna
manarius

This one question comes often :slight_smile:

You can get bone position and change them by adding an action actuator to an object and then using the methods .getChannel() and .setChannel():
http://www.blender.org/documentation/249PythonDoc/GE/GameTypes.BL_ActionActuator-class.html#setChannel

The “channel” it talks about is just the name of the bone.

thanks a lot.

gonna try this out now

finally my cat is going to turn around
MIAU!

greetings
manarius

edit:
now that this newly gathered knowledge had time to sink into my memory i realised that i read about it and tried to memorize it.

its in the ACTION actuator, not in the Armature :wink:

Hey Manarius, If you know how to do this, could you explain it for newbies :o. It would be greatly apreciated.

Thanks

first of all:
i’m a newb too :wink:

i tested the setchannel function and played around with it a bit.

see the attached blend to test it.

you can do:
scale - arrow keys up and down
rotate - arrow keys left and right
move - WASD

space - play an action which is keyframed and on a separate controller

as you will clearly see as soon as you rotate the object, is that i have no idea how to rotate the object using the quat matrix.

  1. is it possible to access an action which currently is cont.activate()d ?
    if you rotate the armature in the demo i attached and press space,
    you will see, that the armature rotates back to the standard rotation of the
    action. does this mean, that i can only access the channel of the bone once,
    either using python or using an action?
    or do i have to rewrite the active actions quat channel every frame?=

  2. is it possible to mirror all the bones of an armature using python within the gameengine?
    left hand <->right hand
    left foot <-> right foot
    and so on?

  3. why does the rotation get slower at an certain angle?= do i have to reset it? whats the max value i should use?

#point 4 was WRONG! see next post
4. seems as if 180° would be equal to 314.1, but ~150-170° would be equal ~1.0-2??
is there some math going on involving pi? as i momentarily only need 180° turning anything is fine atm, but this exponential curve is very steep :confused:

greetings again,
have fun with that blend,
manarius

edit:
i overworked the blend, fixed some bugs and added an second action to the second bone,
just to show how you can activate two actions in one armature.
the restriction is: only one action per bone per frame, not per armature.

Attachments

action_setchannel_test.blend (218 KB)

I’ve been looking at quaternions for a while and have gained a small understanding.

I hope that thie following will improve your understanding rather than confuse you, quaternions still confuse me. :spin:

If a is the angle of rotation and the quaternion follows (W, X, Y, Z) notation then the vector (x, y, z) about which the rotation occurs can be found simply by:

W = cos(a/2)
angle = a = 2 * arcos(W)
x = X * sin(a/2)
y = Y * sin(a/2)
z = Z * sin(a/2)

My understanding is that X, Y, Z are the strength of rotation about an axis and that W is the influence of the original orientation. To rotate about an axis, both the strength of the rotation about that axis must increase and the influence of the original orientation must decrease.

Note that the angle of rotation is halved because quaternions have double cover over a rotation allowing for rotations of +/-360 degrees for a total measurable rotation of 720 degrees. It is this property that removes the possibility for errors through gimball lock.

It should also be noted that only unit quaternions are appropriate for use with 3d rotations and orientations. ie. sqrt(W2 + X2 + Y2 + Z2) = 1 where W**2 indicates W squared, etc.

1: I think that the actuator needs to be set/activated every frame.

2: Possibly, by applying the inverse of the quaternions from one side of the body to the other side. (Reverse the signs on each component of the quaternion)

3: As pointed out above, you need to reduce the W term as you increase any other term. Considering rotation about the x axis and remembering that the value is calculated from a/2…
No rotation, the identity quaternion, is (1,0,0,0)
90 degrees rotation is achieved by setting W to cos(45) and X to sin(45) --> quat = (0.707, 0,707,0,0)
180 degrees rotation is achieved by setting W to 0 and X to 1 (0 is cos(90) and 1 is sin(90) --> quat = (0, 1, 0, 0)
250 degrees rotation is achieved by setting W to cos(125) and X to sin(125) --> quat = (-0.707, 0.707, 0, 0)
360 degrees rotation is achieved by setting W to -1 and X to 0 (-1 is cos(180) and 0 is sin(180)) --> quat = (-1, 0, 0, 0)

4: I hope my other points have answered this one for you. If the quaternion that you’re using is not a unit quaternion the Blender is normalizing it internally since only unit quaternions are valid for representing rotations (I think this is how it works…) so your values will be changed. Try normalizing the quaternion that you’re using and see if this gives more predictable results.

Edit: I really hope this helped rather than confused you. I’ve found this to be the most helpful resource that I found on the subject.

:eek:… humm… algebra…

Uuuh… I don’t want to take over that topic but I have a similar problem… I don’t know if it was aswered but…

I have 2 cube… the bottom one rotate left and right with the mouse… the top one parented to the bottom one rotate up and down with the mouse… SO… Is it possible to set the armature to be in the looking up pose when the cube look up and the bottom pose when the cube look down with plenty of in-betweens ???

Sorry for interupting your algebra lessons senseï… I’m just realy confused. If my question is stupid or impossible, pls ignore me :o.

@Réwii93: Actions would be best for this. As you can see from my previous post, it’s not mundane to set the bone rotations using a script yet. :wink:

As an example, I’ll suggest a method of looking up/down.

Make your up/down action over the course of 90 frames with the first frame looking straight ahead and the last frame looking straight up. These 90 frames will correspond to 90 degrees.

Create a property on the object called UpDown and make it a float property.

Connect the action up using Always --> And --> Action

In the FrameProp box of the action actuator type UpDown. This will set the frame of the action to the property UpDown.

[edit]
You can check that everything is working up to this point by setting up keyboard controls to change the value of UpDown:

Keyboard sensor (up arrow) --> And --> Property actuator

Set up the property actuator to Add. Set Prop to UpDown. Set Value to 1 or 0.5 or any positive number.

Keyboard sensor (down arrow) --> And --> Property actuator

Set up the property actuator to Add. Set Prop to UpDown. Set Value to -1 or -0.5 or any negative number.

The action should now be keyboard controlled.
[/edit]

Now for the tricky bit… You need to modify a mouselook script so that when the mouse is moved up and down it will increment/decrement the property UpDown. Make sure it checks for max/min values of 90/0.

Assuming that everything is correct, the action should now be driven by the mouse movement.

Dude, you are a real help in this forum :yes:. I’ll try modifying my mouselook and I’ll tell you all if it worked (maybe make a tutorial too :D).

Thanks again for your time.

If you find quaternions complicated you could just convert it to something else. The Mathutils module has enough tools for that. For example you could get a rotation matrix from the quaternion using the .toMatrix() method:
http://www.blender.org/documentation/249PythonDoc/GE/Mathutils.Quaternion-class.html#toMatrix

Or for your case where you simply want a bone to track to an object. You could get the vector from point a to b (which is simply the difference between the points in b and the points in a) and then you transform that vector to a quaternion using the Vector.toTrackQuat() method:
http://www.blender.org/documentation/249PythonDoc/GE/Mathutils.Vector-class.html#toTrackQuat

And you use that value on the quaternion part of the .setChannel() matrix. You wouldn’t need to understand how quaternions work at all.

thanks you all,

gonna play around with the information you all were so kind to provide here :slight_smile:

i think that i finally understood, what this mysterious W part of the quaternion is, thanks for that funkywyrm. seems like i finally can overcome the negative conditioning concerning math, thanks for that link, it is really usefull

vibronazo: those are some very usefull methods you describe, gonna try those :slight_smile:

although my head is still spinning, i at least got some floor under my feet :wink:

you all RULE!!!1einseinself!

greetings
manarius

could we create ragdoll, with this method?:o

@Hellooo: Yes, I think rag doll mesh deformation is definately possible using either of the methods highlighted above.

But… and it’s a big ‘but’…

Creating, managing and driving x, y and z location, scale and rotation actions (9 actions, 6 if you leave out scale) for every bone in anything but the most mundane armature (such as above, only for the head) would be a formidable task, especially since the creation and linking of logic bricks cannot (currently) be scripted.

and…

When scripting using setChannel() and the 3-variable loc, scale, rot arguments, each rotation must be given in bone space. Bone space is rotated by every bone that a given bone is parented to right up to the root bone. These rotations must be combined into the orientation of bone space. Then using the difference in a rigid body object’s orientation at rest and the current orientation (rigid body objects would still need to be used to provide the physics calculations), and the calculated bone space, the rotation could be found.

Using this second method I’m making slow progress, but debugging is a PITA because I’m only recently starting to understand quaternions sufficiently to spot what is going wrong and how it can be fixed.