Beispiel #1
0
MinimalBoundingSphere::MinimalBoundingSphere(MathLib::Point3d const& p,
	MathLib::Point3d const& q, MathLib::Point3d const& r)
{
    MathLib::Vector3 const a(p,r);
    MathLib::Vector3 const b(p,q);

    MathLib::Vector3 const cross_ab(crossProduct(a,b));

    if (cross_ab.getLength() > 0)
    {
        double const denom = 2.0 * scalarProduct(cross_ab,cross_ab);
        MathLib::Vector3 const o = (scalarProduct(b,b) * crossProduct(cross_ab, a)
                                   + scalarProduct(a,a) * crossProduct(b, cross_ab))
                                  * (1.0 / denom);
        _radius = o.getLength() + std::numeric_limits<double>::epsilon();
        _center = MathLib::Vector3(p) + o;
    }
    else
    {
        MinimalBoundingSphere two_pnts_sphere;
        if (a.getLength() > b.getLength())
            two_pnts_sphere = MinimalBoundingSphere(p,r);
        else
            two_pnts_sphere = MinimalBoundingSphere(p,q);
        _radius = two_pnts_sphere.getRadius();
        _center = two_pnts_sphere.getCenter();
    }
}
Beispiel #2
0
MinimalBoundingSphere::MinimalBoundingSphere(
	MathLib::Point3d const& p, MathLib::Point3d const& q)
: _radius(std::numeric_limits<double>::epsilon()), _center(p)
{
    MathLib::Vector3 const a(p, q);

    if (a.getLength() > 0)
    {
        MathLib::Vector3 const o(0.5*a);
        _radius = o.getLength() + std::numeric_limits<double>::epsilon();
        _center = MathLib::Vector3(p) + o;
    }
}
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;
}
Beispiel #4
0
MinimalBoundingSphere::MinimalBoundingSphere(MathLib::Point3d const& p,
	MathLib::Point3d const& q,
	MathLib::Point3d const& r,
	MathLib::Point3d const& s)
{
    MathLib::Vector3 const a(p, q);
    MathLib::Vector3 const b(p, r);
    MathLib::Vector3 const c(p, s);

    if (!GeoLib::isCoplanar(p, q, r, s))
    {
        double const denom = 2.0 * GeoLib::scalarTriple(a,b,c);
        MathLib::Vector3 const o = (scalarProduct(c,c) * crossProduct(a,b)
                                  + scalarProduct(b,b) * crossProduct(c,a)
                                  + scalarProduct(a,a) * crossProduct(b,c))
                                  * (1.0 / denom);

        _radius = o.getLength() + std::numeric_limits<double>::epsilon();
        _center = MathLib::Vector3(p) + o;
    }
    else
    {
        MinimalBoundingSphere const pqr(p, q , r);
        MinimalBoundingSphere const pqs(p, q , s);
        MinimalBoundingSphere const prs(p, r , s);
        MinimalBoundingSphere const qrs(q, r , s);
        _radius = pqr.getRadius();
        _center = pqr.getCenter();
        if (_radius < pqs.getRadius())
        {
            _radius = pqs.getRadius();
            _center = pqs.getCenter();
        }
        if (_radius < prs.getRadius())
        {
            _radius = prs.getRadius();
            _center = prs.getCenter();
        }
        if (_radius < qrs.getRadius())
        {
            _radius = qrs.getRadius();
            _center = qrs.getCenter();
        }
    }
}
void MeshSurfaceExtraction::get2DSurfaceElements(const std::vector<MeshLib::Element*> &all_elements, std::vector<MeshLib::Element*> &sfc_elements, const MathLib::Vector3 &dir, double angle, unsigned mesh_dimension)
{
	if (mesh_dimension<2 || mesh_dimension>3)
		ERR("Cannot handle meshes of dimension %i", mesh_dimension);

	bool const complete_surface = (MathLib::scalarProduct(dir, dir) == 0);

	double const pi (boost::math::constants::pi<double>());
	double const cos_theta (std::cos(angle * pi / 180.0));
	MathLib::Vector3 const norm_dir (dir.getNormalizedVector());

	for (auto elem = all_elements.cbegin(); elem != all_elements.cend(); ++elem)
	{
		const unsigned element_dimension ((*elem)->getDimension());
		if (element_dimension < mesh_dimension)
			continue;

		if (element_dimension == 2)
		{
			if (!complete_surface)
			{
				MeshLib::Element* face = *elem;
				if (MathLib::scalarProduct(FaceRule::getSurfaceNormal(face).getNormalizedVector(), norm_dir) > cos_theta)
					continue;
			}
			sfc_elements.push_back(*elem);
		}
		else
		{
			if (!(*elem)->isBoundaryElement())
				continue;
			const unsigned nFaces ((*elem)->getNFaces());
			for (unsigned j=0; j<nFaces; ++j)
			{
				if ((*elem)->getNeighbor(j) != nullptr)
					continue;

				auto const face = std::unique_ptr<MeshLib::Element const>{(*elem)->getFace(j)};
				if (!complete_surface)
				{
					if (MathLib::scalarProduct(FaceRule::getSurfaceNormal(face.get()).getNormalizedVector(), norm_dir) < cos_theta)
					{
						continue;
					}
				}
				if (face->getGeomType() == MeshElemType::TRIANGLE)
					sfc_elements.push_back(new MeshLib::Tri(*static_cast<const MeshLib::Tri*>(face.get())));
				else
					sfc_elements.push_back(new MeshLib::Quad(*static_cast<const MeshLib::Quad*>(face.get())));
			}
		}
	}
}
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;    
}