コード例 #1
0
double sKinematics::CalAngle(MathLib::Vector3 vBase, MathLib::Vector3 vMeasure)
{
	double theta;
	MathLib::Vector3 vOrtho;
	MathLib::Vector3 vDir;
	theta = acos( vBase.Dot(vMeasure) / (vBase.Norm()*vMeasure.Norm()) );

	vOrtho = vBase.Cross(vMeasure);
	vOrtho.Normalize();
	vDir = vOrtho.Cross(vBase);

	if( vDir.Dot(vMeasure) > 0 ) return theta;
	else return -theta;
}
コード例 #2
0
void    HandSkinControllerThread::PredictPoseFromAngle(){
    // Apply the model and rock the field
    bool bdm = bDebugMode;
    bDebugMode = false;

    if(bDebugMode) cout << "Predicting pose from angle *********"<<endl;


    // Count the number of valid contact

    // Reliability measure for each fingertip
    double  validFTip[FINGERS_COUNT];
    int     validFTipCount = 0;

    if(bNoMissingCheck){
        // If we don't care, let's move on
        for(int i=0;i<FINGERS_COUNT;i++){
            validFTip[i] = 1.0;        
        }
        validFTipCount = FINGERS_COUNT;
    }else{
        for(int i=0;i<FINGERS_COUNT;i++){
            // Higher than min threshold?
            if(mSFingerTip[i][0] >= FTIPTHRESHOLD){
                validFTipCount++;
                // Higher than max threshold?
                if(mSFingerTip[i][0] >= FTIPTHRESHOLDMAX){
                    validFTip[i] = 1.0;
                }else{
                    // Save validity between 0 and 1
                    validFTip[i] = (mSFingerTip[i][0]-FTIPTHRESHOLD)/(FTIPTHRESHOLDMAX-FTIPTHRESHOLD);
                }
            }else{
                validFTip[i] = 0.0;        
            }
        }
    }



    // Additional input weight matrix using the realiability measure
    MathLib::Matrix     inWeights(validFTipCount*3,validFTipCount*3);    
    inWeights.Zero();
    int cnt = 0;
    for(int i=0;i<FINGERS_COUNT;i++){
        if(validFTip[i]>0){
            inWeights(cnt*3+0,i*3+0) = validFTip[i];
            inWeights(cnt*3+1,i*3+1) = validFTip[i];
            inWeights(cnt*3+2,i*3+2) = validFTip[i];
            cnt++;
        }
    }
    
    // Some variables
    MathLib::Vector     inComp(validFTipCount*3);
    MathLib::Vector     outComp(FINGERS_COUNT*2+1+FINGERS_COUNT*1);        
    MathLib::Vector     inV(validFTipCount*3);
    MathLib::Vector     outV(FINGERS_COUNT*2+1+FINGERS_COUNT*1); outV.Zero();
    MathLib::Matrix     sigma(FINGERS_COUNT*2+1+FINGERS_COUNT*1,FINGERS_COUNT*2+1+FINGERS_COUNT*1);

    // Output components indices of the gmm
    for(int i=0;i<outComp.Size();i++)
        outComp(i) = i;
    

    // Input components indices of the gmm
    cnt = 0;
    for(int i=0;i<FINGERS_COUNT;i++){
        if(validFTip[i]>0){
            inComp(cnt++) = outComp.Size()+i*3+0;
            inComp(cnt++) = outComp.Size()+i*3+1;
            inComp(cnt++) = outComp.Size()+i*3+2;
        }
    }

    if(bDebugMode){ cout <<"Vld:  "; for(int i=0;i<FINGERS_COUNT;i++) cout << validFTip[i]<<" "; cout<<endl;}
    if(bDebugMode) cout <<"InC:  " << inComp<<endl;
    
    // Filling the input vector with sensor data
    cnt = 0;
    for(int i=0;i<FINGERS_COUNT;i++){
        if(validFTip[i]>0){
            inV(cnt++) = mSFingerTipDir[i][0];
            inV(cnt++) = mSFingerTipDir[i][1];
            inV(cnt++) = mSFingerTipDir[i][2];
        }
    }

    if(bDebugMode) cout <<"InV:  "<< inV<<endl;


    MathLib::Vector grad,gradNoExp;
    MathLib::Vector inV2,inV0;
    inV2 = inV;
    inV0 = inV;
    

    if(validFTipCount>0){
        // We have at least one valid input
        if(bGradientAscent){
            // We enjoy gradient ascent

            // Get the probability that input query point is in the model            
            double val = mGMModel.GetPx(inV2,inComp,&inWeights);
            
            // Iterate until we're happy
            int iter = 0;
            int iterNoExp = 0;            
            while(1){
                // Get the gradient of current point
                val = mGMModel.GetGradX(inV2,inComp,grad,&inWeights,&gradNoExp);

                // Get the membership of the current input query point, 
                // if higher than threshold we're done 
                if(val >= exp(-0.5*2.5*2.5))
                    break;

                // Norm of the gradient
                double norm = grad.Norm();
                if(val<1e-12){
                    // Too small? use another safer version in gradNoExp
                    grad = gradNoExp;
                    norm = gradNoExp.Norm();
                    norm = 1.0/norm; 

                    iterNoExp++;

                    if(!isnormal(norm)){
                        // Still a not - number... big failure... but we 
                        // exit still...
                        iter = -1;                    
                        break;
                    }
                }else{
                    // Big enough? Normalize
                    norm = 1.0/norm;                
                }
                // Normalize
                grad *= (-norm);
                // Scale the gradient to a little step size and add it 
                // to the query point
                grad.ScaleAddTo(0.01,inV2);

                // Normalization of the query point (i.e. the contact normals
                // should be better unit norm
                int cnt2 = 0;
                for(int i=0;i<FINGERS_COUNT;i++){
                    if(validFTip[i]>0){
                        MathLib::Vector3 vn;
                        vn(0) = inV2(cnt2+0);
                        vn(1) = inV2(cnt2+1);
                        vn(2) = inV2(cnt2+2);
                        vn.Normalize();
                        inV2(cnt2+0) = vn(0);
                        inV2(cnt2+1) = vn(1);
                        inV2(cnt2+2) = vn(2);
                        cnt2 += 3;
                    }
                }

                iter++;
                if(iter>300){
                    // Too much iteration.... again bg failure, exit gracefully
                    break;
                }
            }
            if(bDebugMode) cout << "  Gradient Descent: # iterations : "<<iter<< "("<<iterNoExp<<")"<<endl;


            if((iter<0)||(iter>300)){
                mSFingerDesCoupling.Identity();
                if(bDebugMode){
                    cout << "  Failed: Membership Value (threshold: "<<exp(-0.5*2.5*2.5)<<") -> "<<val <<endl;
                    cout << endl<<endl;
                }
                bDebugMode= bdm;
                return;
            }
        }
    }
    
    
    if(bDebugMode) cout <<"Input: "<< inV<<endl;
    
    // Finally do the regression :)
    inV = inV2;
    double res   = mGMModel.doRegression( inV , inComp, outComp, outV, sigma,&inWeights);

    if(bDebugMode) cout << "Confidence: "<<res<<endl;    
    if(bDebugMode) cout << "Output: "<<outV<<endl;

    // Desired position
    for(int i=0;i<FINGERS_COUNT;i++){
        mSFingerDesPos[i][0] = outV(1+i*2+0);// / mPosFactor;
        mSFingerDesPos[i][1] = outV(1+i*2+1);// / mPosFactor;
    }
    // Desired pressure
    for(int i=0;i<FINGERS_COUNT;i++){
        mSFingerDesTip[i][0] = outV(1+FINGERS_COUNT*2+i)+2.0;
        
        // Tweaking the output sigma matrice (identiting the pressure part,
        // and keeping the position part only (for the force-position control 
        // switch))
        sigma.SetRow(0.0,1+FINGERS_COUNT*2+i);
        sigma.SetColumn(0.0,1+FINGERS_COUNT*2+i);
        sigma(1+FINGERS_COUNT*2+i,1+FINGERS_COUNT*2+i) = 1.0;
    }

    // Inverting the sigma matrix
    MathLib::Matrix nsigma(sigma);
    nsigma.Identity();
    nsigma *= 10.0; // A bit more power in the diagonal
    nsigma += sigma;
        
    // Inverse and store it for later use
    nsigma.InverseSymmetric(mSFingerDesCoupling);    
    

    // More coping fo data here and there
    mJointsTargetPredPos = mJointsRest;
    for(int i=mJointsFingerOffset+1;i<mJointsSize-1;i++){
        mJointsTargetPredPos(i) = outV(i-mJointsFingerOffset-1);
    }

    bDebugMode= bdm;    
}