Calculating final Bone/PoseBone matrices I'm writing an exporter and am trying to export the animations but I'm not certain of what space the matrices are in or what they're relative to (if anything) and the docs don't really give much info at all about any class variable.

I believe the Bind Pose matrix should come from PoseBone.bone.matrix_local. Since it's being called a 'local' matrix I would assume that it's relative to its parent but then the docs say it's in armature-space. What does this matrix really represent?

I'm trying to export the final pose matrix for each bone for a given frame but I tend to either have very incorrect matrices or they seem to not be inheriting a rotation somewhere.

rig_ui.py calculates a pose matrix like this:

rest = posebone.bone.matrix_local.inverted()
par_rest = posebone.bone.matrix_local.inverted()
par_inv = posebone.parent.matrix.inverted()
final = rest * par_rest * par_inv * posebone.matrix


This results in the armature pose seeming to lose an ancestor's rotation somewhere. What I don't understand is why none of the other scripts actually use ancestor's matrices if bone.matrix_local actually is relative to its parent. Won't it need to have accumulated every ancestor? Am I misunderstanding what space either bone.matrix_local or posebone.matrix is in?

Some scripts/exporters are also using the inverse of the pose bone's parent's matrix or the inverse of the bone's parent's matrix_local (before applying that to that bone's matrix_local which is not inverted). My understanding was that only the bind pose matrices need to be inverted and ALL of them must be inverted.
A straight-forward approach using convert_space() and a matrix to convert bone space:

import bpy

arma_ob = bpy.context.object
mesh_ob = bpy.data.objects['Suzanne']

pose_bone = bpy.context.active_pose_bone

bone_space = Matrix(((1,0,0,0),(0,0,1,0),(0,-1,0,0),(0,0,0,1)))
mat = arma_ob.convert_space(pose_bone, pose_bone.matrix, 'POSE', 'WORLD') * bone_space

mesh_ob.matrix_world = mat


Add a monkey and select a pose bone, then run the above script. Then Suzanne should look in pose bone direction. Note that bone direction is +Y, so it's (0,1,0) for a bone pointing upwards (Z).