Beispiel #1
0
def testDerivatives(skelDict, chanValues, effectorData, effectorTargets):
    ''' skelDict specifies a skeleton.
		Given an initial skeleton pose (chanValues), effectors (ie constraints: joint, offset, weight, target), solve for the skeleton pose.
		Effector weights and targets are 3x4 matrices.
		* Setting 1 in the weight's 4th column makes a position constraint.
		* Setting 100 in the weight's first 3 columns makes an orientation constraint.
	'''
    rootMat = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0]],
                       dtype=np.float32)
    effectorJoints, effectorOffsets, effectorWeights, usedChannels, usedCAEs, usedCAEsSplits = effectorData
    jointParents = skelDict['jointParents']
    Gs = skelDict['Gs']
    Ls = skelDict['Ls']
    jointChans = skelDict['jointChans']
    jointChanSplits = skelDict['jointChanSplits']
    numChannels = jointChanSplits[-1]
    numEffectors = len(effectorJoints)
    numUsedChannels = len(usedChannels)
    channelMats = np.zeros((numChannels, 3, 4), dtype=np.float32)
    usedEffectors = np.where(effectorWeights.reshape(-1) != 0)[0]
    numUsedEffectors = len(usedEffectors)
    effectors = np.zeros((numEffectors, 3, 4), dtype=np.float32)
    residual = np.zeros((numEffectors, 3, 4), dtype=np.float32)
    derrors = np.zeros((numUsedChannels, numEffectors, 3, 4), dtype=np.float32)
    steps = np.ones((numUsedChannels), dtype=np.float32) * 1.0
    steps[np.where(jointChans[usedChannels] < 3)[0]] = 30.
    delta = np.zeros((numUsedChannels), dtype=np.float32)
    JJTB = np.zeros((numEffectors * 12), dtype=np.float32)
    Character.pose_skeleton_with_chan_mats(channelMats, Gs, chanValues,
                                           rootMat)
    bestScore = ISCV.pose_effectors(effectors, residual, Gs, effectorJoints,
                                    effectorOffsets, effectorWeights,
                                    effectorTargets)
    print(bestScore, chanValues[usedChannels])
    ISCV.derror_dchannel(derrors, channelMats, usedChannels, usedCAEs,
                         usedCAEsSplits, jointChans, effectors,
                         effectorWeights)
    JT = derrors.reshape(numUsedChannels, -1)
    B = residual.reshape(-1)
    residual2 = np.zeros(residual.shape, dtype=np.float32)
    # JT[ci] = dresidual_dci
    for uci in xrange(numUsedChannels):
        ci = usedChannels[uci]
        tmp = chanValues[ci]
        d_ci = max(0.001, abs(chanValues[ci] * 0.001))
        chanValues[ci] += d_ci
        Character.pose_skeleton(Gs, skelDict, chanValues, rootMat)
        bestScore = ISCV.pose_effectors(effectors, residual2, Gs,
                                        effectorJoints, effectorOffsets,
                                        effectorWeights, effectorTargets)
        #print (bestScore)
        diff = (residual2.reshape(-1) - B) / -d_ci
        if np.dot(JT[uci], diff) / np.sqrt(1e-10 + np.dot(JT[uci], JT[uci]) *
                                           np.dot(diff, diff)) < 0.99:
            print(
                uci, ci,
                np.dot(JT[uci], diff) /
                np.sqrt(1e-10 + np.dot(JT[uci], JT[uci]) * np.dot(diff, diff)))
        chanValues[ci] = tmp
Beispiel #2
0
def solveIK(skelDict,
            chanValues,
            effectorData,
            effectorTargets,
            outerIts=10,
            rootMat=None):
    """
	Given an initial skeleton pose (chanValues), effectors (ie constraints: joint, offset, weight, target), solve for the skeleton pose.
	Effector weights and targets are 3x4 matrices.
		* Setting 1 in the weight's 4th column makes a position constraint.
		* Setting 100 in the weight's first 3 columns makes an orientation constraint.
		
	Args:
		skelDict (GskelDict): The Skeleton to process
		chanValues (float[]): Initial pose of the skeleton as Translation and many rotations applied to joints in the skelDict.
		effectorData (big o'l structure!):
			effectorJoints, effectorOffsets, effectorWeights, usedChannels, usedChannelWeights, usedCAEs, usedCAEsSplits
		effectorTargets (?): What's this?
		outerIts (int): IK Iterations to solve the skeleton. Default = 10
		rootMat (float[3][4]): reference frame of the Skeleton. Default = None
		
	Returns:
		None: The result is an update of the skelDict to the solution - chanValues, channelMats, and Gs.
		
	Requires:
		Character.pose_skeleton_with_chan_mats
		ISCV.pose_effectors
		ISCV.derror_dchannel
		ISCV.JTJ
	"""
    effectorJoints, effectorOffsets, effectorWeights, usedChannels, usedChannelWeights, usedCAEs, usedCAEsSplits = effectorData
    jointParents = skelDict['jointParents']
    Gs = skelDict['Gs']
    Ls = skelDict['Ls']
    jointChans = skelDict['jointChans']
    jointChanSplits = skelDict['jointChanSplits']
    numChannels = jointChanSplits[-1]
    numEffectors = len(effectorJoints)
    numUsedChannels = len(usedChannels)
    channelMats = np.zeros((numChannels, 3, 4), dtype=np.float32)
    #usedEffectors   = np.array(np.where(np.sum(effectorWeights,axis=(1,2)) != 0)[0], dtype=np.int32)
    usedEffectors = np.array(np.where(effectorWeights.reshape(-1) != 0)[0],
                             dtype=np.int32)
    # numUsedEffectors= len(usedEffectors)
    effectors = np.zeros((numEffectors, 3, 4), dtype=np.float32)
    residual = np.zeros((numEffectors, 3, 4), dtype=np.float32)
    derrors = np.zeros((numUsedChannels, numEffectors, 3, 4), dtype=np.float32)
    # steps           = np.ones((numUsedChannels),dtype=np.float32)*0.2
    # steps[np.where(jointChans[usedChannels] < 3)[0]] = 30.
    # steps = 1.0/steps
    delta = np.zeros((numUsedChannels), dtype=np.float32)
    # JJTB            = np.zeros((numEffectors*12),dtype=np.float32)
    JTJ = np.zeros((numUsedChannels, numUsedChannels), dtype=np.float32)
    JTB = np.zeros((numUsedChannels), dtype=np.float32)
    JT = derrors.reshape(numUsedChannels, -1)
    JTJdiag = np.diag_indices_from(JTJ)
    B = residual.reshape(-1)
    # TODO, calculate the exact requirements on the tolerance
    B_len = len(B)
    tolerance = 0.00001
    it_eps = (B_len**0.5) * tolerance
    for it in xrange(outerIts):
        # TODO, only usedChannels are changing, only update the matrices that have changed after the first iteration.
        # TODO Look into damping, possibly clip residuals?
        # updates the channelMats and Gs
        Character.pose_skeleton_with_chan_mats(channelMats, Gs, skelDict,
                                               chanValues, rootMat)
        bestScore = ISCV.pose_effectors(effectors, residual, Gs,
                                        effectorJoints, effectorOffsets,
                                        effectorWeights, effectorTargets)
        if np.linalg.norm(B) < it_eps: break  # early termination
        ISCV.derror_dchannel(derrors, channelMats, usedChannels,
                             usedChannelWeights, usedCAEs, usedCAEsSplits,
                             jointChans, effectors, effectorWeights)
        # if True: # DLS method : solve (JTJ + k^2 I) delta = JTB
        ISCV.JTJ(
            JTJ, JTB, JT, B,
            usedEffectors)  #np.dot(JT, B, out=JTB); np.dot(JT, JT.T, out=JTJ)
        JTJ[JTJdiag] += 1
        JTJ[JTJdiag] *= 1.1
        _, delta[:], _ = LAPACK.dposv(JTJ, JTB)  # Use Positive Definite Solver
        # Use General Solver
        # delta[:] = np.linalg.solve(JTJ, JTB)
        # elif it==0: # SVD method: solve J delta = B
        # 	delta[:] = np.linalg.lstsq(JT.T[usedEffectors], B[usedEffectors], rcond=0.0001)[0].reshape(-1)
        # else:     # J transpose method
        # 	testScale = ISCV.J_transpose(delta, JJTB, JT, B)
        # 	#np.dot(JT, B, out=delta); np.dot(JT.T,delta,out=JJTB); delta *= np.dot(B,JJTB)/(np.dot(JJTB,JJTB)+1.0)
        #scale = np.max(np.abs(delta*steps))
        #if scale > 1.0: delta *= 1.0/scale
        #np.clip(delta,-steps,steps,out=delta)
        chanValues[usedChannels] += delta
        # TODO: add channel limits
        #bestScore = ISCV.lineSearch(chanValues, usedChannels, delta, Gs, Ls, jointParents, jointChans, jointChanSplits,
        #							rootMat, effectorJoints, effectorOffsets, effectorWeights, effectorTargets, innerIts, bestScore)
    #print np.mean(B*B)
    Character.pose_skeleton(Gs, skelDict, chanValues, rootMat)
Beispiel #3
0
def drawSkeleton(win, locationName, attrs, interface, picked):
    from UI import GLSkel, COLOURS
    if 'skelDict' not in attrs: return

    boneColour = COLOURS['Bone']
    if 'boneColour' in attrs: boneColour = attrs['boneColour']

    skelDict = attrs['skelDict']
    Gs = attrs['Gs'] if 'Gs' in attrs else skelDict['Gs']

    skelLayer = None
    if locationName not in win.getLayers() or 'override' in attrs:
        skel = GLSkel(skelDict['Bs'],
                      Gs,
                      mvs=get(skelDict, 'markerOffsets'),
                      mvis=get(skelDict, 'markerParents'),
                      bone_colour=boneColour)
        if 'subjectName' in attrs: skel.setName(attrs['subjectName'])
        skelLayer = win.setLayer(locationName, skel)
    else:
        skelLayer = win.getLayer(locationName)
        skelLayer.setPose(Gs)

    if skelLayer: skelLayer.setBoneColour(boneColour)

    layer = win.getLayer(locationName)
    if layer: layer.setVisible(isVisible(attrs))

    # For debugging, plot markers to joint mapping
    if 'jointMarkersMap' in attrs:
        from GCore import SolveIK
        effectorData = SolveIK.make_effectorData(skelDict)
        useMarkers = True
        if useMarkers:
            effectorLabels = np.array(
                [int(mn) for mn in skelDict['markerNames']], dtype=np.int32)
            x3ds, x3ds_labels = SolveIK.skeleton_marker_positions(
                skelDict, skelDict['rootMat'], skelDict['chanValues'],
                effectorLabels, effectorData, skelDict['markerWeights'])
        else:
            import ISCV
            effectorTargets = np.zeros_like(effectorData[1])
            numEffectors = len(effectorTargets)
            effectors = np.zeros((numEffectors, 3, 4), dtype=np.float32)
            residual = np.zeros((numEffectors, 3, 4), dtype=np.float32)
            sc = ISCV.pose_effectors(effectors, residual, skelDict['Gs'],
                                     effectorData[0], effectorData[1],
                                     effectorData[2], effectorTargets)
            x3ds = effectors[:, :3, 3]

        [j_inds, m_inds, colours] = attrs['jointMarkersMap']

        effectorIdx = 0
        for i, (ji, mi) in enumerate(zip(j_inds, m_inds)):
            if not ji or not mi: continue
            mappingAttrs = {
                'colour': (0.1, 0.4, 0.1, 0.5),
                'edgeColour': colours[i],
                'pointSize': 8
            }
            if not useMarkers:
                mi = min(effectorIdx, len(x3ds) - 1)
                effectorIdx += 1
                mappingAttrs['x1'] = np.array([x3ds[mi]], dtype=np.float32)
            else:
                mappingAttrs['x1'] = x3ds[mi]

            mappingAttrs['x0'] = skelDict['Gs'][ji][:, :3, 3]

            childName = os.path.join(
                locationName, '/',
                'jointToMarkers_%s' % skelDict['jointNames'][ji[0]])
            drawEdges(win, childName, mappingAttrs, interface, picked)