Пример #1
0
 MatrixXd ConstraintDynamics::getContactMatrix() const {
     MatrixXd E(MatrixXd::Zero(getNumContacts() * mNumDir, getNumContacts()));
     MatrixXd column(MatrixXd::Ones(mNumDir, 1));
     for (int i = 0; i < getNumContacts(); i++) {
         E.block(i * mNumDir, i, mNumDir, 1) = column;
     }
     return E;
 }
Пример #2
0
/*
        void ContactDynamics::updateBasisMatrix() {
            mB = MatrixXd::Zero(getNumTotalDofs(), getNumContacts() * getNumContactDirections());
            for (int i = 0; i < getNumContacts(); i++) {
                ContactPoint& c = mCollisionChecker->getContact(i);
                Vector3d p = c.point;
                int skelID1 = mBodyIndexToSkelIndex[c.bdID1];
                int skelID2 = mBodyIndexToSkelIndex[c.bdID2];

                MatrixXd B21;
                MatrixXd B12;
                if (!mSkels[skelID1]->getImmobileState()) {
                    int index1 = mIndices[skelID1];
                    int NDOF1 = c.bd1->getSkel()->getNumDofs();
                    B21 = getTangentBasisMatrix(p, c.normal);
                    MatrixXd J21 = getJacobian(c.bd1, p);

                    mB.block(index1, i * getNumContactDirections(), NDOF1, getNumContactDirections()) = J21.transpose() * B21;

                    //  cout << "B21: " << B21 << endl;
                }

                if (!mSkels[skelID2]->getImmobileState()) {
                    int index2 = mIndices[skelID2];
                    int NDOF2 = c.bd2->getSkel()->getNumDofs();
                    if (B21.rows() == 0)
                        B12 = getTangentBasisMatrix(p, -c.normal);
                    else
                        B12 = -B21;
                    MatrixXd J12 = getJacobian(c.bd2, p);
                    mB.block(index2, i * getNumContactDirections(), NDOF2, getNumContactDirections()) = J12.transpose() * B12;

                    //  cout << "B12: " << B12 << endl;

                }
            }
            return;
        }
        */
MatrixXd ContactDynamics::getContactMatrix() const {
    int numDir = getNumContactDirections();
    MatrixXd E(MatrixXd::Zero(getNumContacts() * numDir, getNumContacts()));
    MatrixXd column(MatrixXd::Ones(numDir, 1));
    for (int i = 0; i < getNumContacts(); i++) {
        E.block(i * numDir, i, numDir, 1) = column;
    }
    //        return E / (mDt * mDt);
    return E;
}
Пример #3
0
void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btTransform& trB)
{
	int i;
#ifdef DEBUG_PERSISTENCY
	printf("refreshContactPoints posA = (%f,%f,%f) posB = (%f,%f,%f)\n",
		trA.getOrigin().getX(),
		trA.getOrigin().getY(),
		trA.getOrigin().getZ(),
		trB.getOrigin().getX(),
		trB.getOrigin().getY(),
		trB.getOrigin().getZ());
#endif //DEBUG_PERSISTENCY
	/// first refresh worldspace positions and distance
	for (i=getNumContacts()-1;i>=0;i--)
	{
		btManifoldPoint &manifoldPoint = m_pointCache[i];
		manifoldPoint.m_positionWorldOnA = trA( manifoldPoint.m_localPointA );
		manifoldPoint.m_positionWorldOnB = trB( manifoldPoint.m_localPointB );
		manifoldPoint.m_distance1 = (manifoldPoint.m_positionWorldOnA -  manifoldPoint.m_positionWorldOnB).dot(manifoldPoint.m_normalWorldOnB);
		manifoldPoint.m_lifeTime++;
	}

	/// then 
	btScalar distance2d;
	btVector3 projectedDifference,projectedPoint;
	for (i=getNumContacts()-1;i>=0;i--)
	{
		
		btManifoldPoint &manifoldPoint = m_pointCache[i];
		//contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction)
		if (!validContactDistance(manifoldPoint))
		{
			removeContactPoint(i);
		} else
		{
			//contact also becomes invalid when relative movement orthogonal to normal exceeds margin
			projectedPoint = manifoldPoint.m_positionWorldOnA - manifoldPoint.m_normalWorldOnB * manifoldPoint.m_distance1;
			projectedDifference = manifoldPoint.m_positionWorldOnB - projectedPoint;
			distance2d = projectedDifference.dot(projectedDifference);
			if (distance2d  > getContactBreakingThreshold()*getContactBreakingThreshold() )
			{
				removeContactPoint(i);
			} else
			{
				//contact point processed callback
				if (gContactProcessedCallback)
					(*gContactProcessedCallback)(manifoldPoint,m_body0,m_body1);
			}
		}
	}
#ifdef DEBUG_PERSISTENCY
	DebugPersistency();
#endif //
}
typename BVolCollision<BasicTraits,BVOL>::ResultT
BVolCollision<BasicTraits,BVOL>::BVolBVolCollision 
(GroupType* g0, GroupType* g1)
{
   ++m_numBVolBVolTests;
   // perform BV-BV overlap test
   Real t = bvolIntersect(g0->getBVol(), g1->getBVol());
   if (t < 0.0f) {
      return DoubleTraverserBase<BasicTraits>::QUIT;
   }
   const DoubleTraverserFixedBase<BasicTraits>* trav 
     = dynamic_cast<const DoubleTraverserFixedBase<BasicTraits>*>(getTraverser());
   if (trav != NULL 
       && trav->getDepth0() == getCurrentDepth0(trav, g0) 
       && trav->getDepth1() == getCurrentDepth1(trav, g1)) {
      // Keep track of colliding pairs
      // check if first collision already found
      if (getNumContacts() == 0) {
	 m_contacts.push_back(CollisionPair((AdapterType*)g0->findLeaf(), 
					    (AdapterType*)g1->findLeaf()));
	 CollisionInterface<OpenSGTriangleBase<BasicTraits>,Real> 
	   result(m_contacts[m_contacts.size()-1]);
	 result.getData() = t;
      }
      CollisionInterface<OpenSGTriangleBase<BasicTraits>,Real> 
	result(m_contacts[0]);
      if (t < result.getData()) {
	 result.getData() = t;
	 m_contacts[0].setFirst((AdapterType*)g0->findLeaf());
	 m_contacts[0].setSecond((AdapterType*)g1->findLeaf());
      }
   }
   return DoubleTraverserBase<BasicTraits>::CONTINUE;
}
Пример #5
0
void ContactDynamics::applySolution() {
    const int c = getNumContacts();

    // First compute the external forces
    VectorXd f_n = mX.head(c);
    VectorXd f_d = mX.segment(c, c * mNumDir);
    VectorXd lambda = mX.tail(c);
    VectorXd forces = mN * f_n;
    forces.noalias() += mB * f_d;

    // Next, apply the external forces skeleton by skeleton.
    int startRow = 0;
    for (int i = 0; i < getNumSkels(); i++) {
        if (mSkels[i]->getImmobileState())
            continue;
        int nDof = mSkels[i]->getNumDofs();
        mConstrForces[i] = forces.segment(startRow, nDof);
        startRow += nDof;
    }

    for (int i = 0; i < c; i++) {
        Contact& contact = mCollisionChecker->getContact(i);
        contact.force.noalias() = getTangentBasisMatrix(contact.point, contact.normal) * f_d.segment(i * mNumDir, mNumDir);
        contact.force += contact.normal * f_n[i];
    }
}
Пример #6
0
int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint)
{
	btAssert(validContactDistance(newPoint));

	int insertIndex = getNumContacts();
	if (insertIndex == MANIFOLD_CACHE_SIZE)
	{
#if MANIFOLD_CACHE_SIZE >= 4
		//sort cache so best points come first, based on area
		insertIndex = sortCachedPoints(newPoint);
#else
		insertIndex = 0;
#endif
		clearUserCache(m_pointCache[insertIndex]);
		
	} else
	{
		m_cachedPoints++;

		
	}
	if (insertIndex<0)
		insertIndex=0;

	btAssert(m_pointCache[insertIndex].m_userPersistentData==0);
	m_pointCache[insertIndex] = newPoint;
	return insertIndex;
}
Пример #7
0
        void ContactDynamics::applySolution() {
            int c = getNumContacts();

            // First compute the external forces
            int nRows = mMInv.rows(); // a hacky way to get the dimension
            VectorXd forces(VectorXd::Zero(nRows));
            VectorXd f_n = mX.head(c);
            VectorXd f_d = mX.segment(c, c * mNumDir);
            VectorXd lambda = mX.tail(c);
            forces = (mN * f_n) + (mB * f_d);

            // Next, apply the external forces skeleton by skeleton.
            int startRow = 0;
            for (int i = 0; i < getNumSkels(); i++) {
                if (mSkels[i]->getImmobileState())
                    continue;
                int nDof = mSkels[i]->getNumDofs();
                mConstrForces[i] = forces.segment(startRow, nDof);
                startRow += nDof;
            }

            for (int i = 0; i < c; i++) {
                ContactPoint& contact = mCollisionChecker->getContact(i);
                contact.force = getTangentBasisMatrix(contact.point, contact.normal) * f_d.segment(i * mNumDir, mNumDir) + contact.normal * f_n[i];
            }
        }
typename PrecomputedAlignCollision<BasicTraits,BVOL>::ResultT
PrecomputedAlignCollision<BasicTraits,BVOL>::BVolBVolCollision (GroupType* g0, GroupType* g1)
{
    // check if first collision already found
    if (getStopFirst() && getNumContacts()>0) {
        return DoubleTraverserBase<BasicTraits>::QUIT;
    }
    ++m_numBVolBVolTests;
    // perform BV-BV overlap test
    const BVOL& dop1 = g0->getBVol();
    const BVOL& dop2 = g1->getBVol();
    const Real* center = g1->getData().getRotationCenter();

    u32 k, kk, mink, maxk;
    Real     min2, max2, correct;
    for (k=0, kk=BVOL::Size; k<BVOL::Size; ++k, ++kk) {
        maxk = m_perm[k];
        mink = m_perm[kk];

        if (maxk < BVOL::Size) {
            max2 =  dop2.maxVector()[maxk] - center[maxk];
            min2 =  dop2.minVector()[maxk] - center[maxk];
        } else {
            max2 = -dop2.minVector()[mink] + center[mink];
            min2 = -dop2.maxVector()[mink] + center[mink];
        }
        min2 *= m_scale;
        max2 *= m_scale;
        correct = m_proj[k].dot(g1->getCenter());
#ifdef GV_WITH_SUBCONES
        min2 = min2*BVOL::unitDopAngleTable(g1->getData().getOccupancy(mink)[m_submask[kk]],
                                            m_mask[kk],
                                            g1->getData().getOuterMost(mink)[m_submask[kk]])
               + correct;
        max2 = max2*BVOL::unitDopAngleTable(g1->getData().getOccupancy(maxk)[m_submask[k]],
                                            m_mask[k],
                                            g1->getData().getOuterMost(maxk)[m_submask[k]])
               + correct;
#else
        min2 = min2*BVOL::unitDopAngleTable(g1->getData().getOccupancy(mink)[0],
                                            m_mask[kk],
                                            g1->getData().getOuterMost(mink)[0])
               + correct;
        max2 = max2*BVOL::unitDopAngleTable(g1->getData().getOccupancy(maxk)[0],
                                            m_mask[k],
                                            g1->getData().getOuterMost(maxk)[0])
               + correct;
#endif
        if (stdMin(dop1.maxVector()[k], max2+m_M1Offset[k]) < stdMax(dop1.minVector()[k], min2+m_M1Offset[k])) {
            return DoubleTraverserBase<BasicTraits>::QUIT;
        }
    }
    return DoubleTraverserBase<BasicTraits>::CONTINUE;
}
Пример #9
0
void ContactDynamics::updateNBMatrices() {
    mN = MatrixXd::Zero(getNumTotalDofs(), getNumContacts());
    mB = MatrixXd::Zero(getNumTotalDofs(), getNumContacts() * getNumContactDirections());
    for (int i = 0; i < getNumContacts(); i++) {
        Contact& c = mCollisionChecker->getContact(i);
        Vector3d p = c.point;
        int skelID1 = mBodyIndexToSkelIndex[c.collisionNode1->getIndex()];
        int skelID2 = mBodyIndexToSkelIndex[c.collisionNode2->getIndex()];

        Vector3d N21 = c.normal;
        Vector3d N12 = -c.normal;
        MatrixXd B21 = getTangentBasisMatrix(p, N21);
        MatrixXd B12 = -B21;

        if (!mSkels[skelID1]->getImmobileState()) {
            int index1 = mIndices[skelID1];
            int NDOF1 = c.collisionNode1->getBodyNode()->getSkel()->getNumDofs();
            //    Vector3d N21 = c.normal;
            MatrixXd J21t = getJacobian(c.collisionNode1->getBodyNode(), p);
            mN.block(index1, i, NDOF1, 1).noalias() = J21t * N21;
            //B21 = getTangentBasisMatrix(p, N21);
            mB.block(index1, i * getNumContactDirections(), NDOF1, getNumContactDirections()).noalias() = J21t * B21;
        }

        if (!mSkels[skelID2]->getImmobileState()) {
            int index2 = mIndices[skelID2];
            int NDOF2 = c.collisionNode2->getBodyNode()->getSkel()->getNumDofs();
            //Vector3d N12 = -c.normal;
            //if (B21.rows() == 0)
            //  B12 = getTangentBasisMatrix(p, N12);
            //else
            //   B12 = -B21;
            MatrixXd J12t = getJacobian(c.collisionNode2->getBodyNode(), p);
            mN.block(index2, i, NDOF2, 1).noalias() = J12t * N12;
            mB.block(index2, i * getNumContactDirections(), NDOF2, getNumContactDirections()).noalias() = J12t * B12;

        }
    }
}
typename BVolCollision<BasicTraits,BVOL>::ResultT
BVolCollision<BasicTraits,BVOL>::PrimBVolCollision 
(AdapterType* p0, GroupType* g1)
{
   ++m_numPrimBVolTests;
   // perform BV-BV overlap test
#if defined(GV_BVOLS_IN_MIXEDTESTS)
   Real t = bvolIntersect(p0->getBVol(), g1->getBVol());

   if (t < 0.0f) {
      return DoubleTraverserBase<BasicTraits>::QUIT;
   }
   const DoubleTraverserFixedBase<BasicTraits>* trav 
     = dynamic_cast<const DoubleTraverserFixedBase<BasicTraits>*>(getTraverser());
   if (trav != NULL 
       && trav->getDepth1() == getCurrentDepth1(trav, g1)) {
      // Keep track of colliding pairs
      // check if first collision already found
      if (getNumContacts() == 0) {
	 m_contacts.push_back(CollisionPair(p0, (AdapterType*)g1->findLeaf()));
	 CollisionInterface<OpenSGTriangleBase<BasicTraits>,Real> 
	   result(m_contacts[m_contacts.size()-1]);
	 result.getData() = t;
      }
      CollisionInterface<OpenSGTriangleBase<BasicTraits>,Real> 
	result(m_contacts[0]);
      if (t < result.getData()) {
	 result.getData() = t;
	 m_contacts[0].setFirst(p0);
	 m_contacts[0].setSecond((AdapterType*)g1->findLeaf());
      }
   }
#else
   // Transform from model space 0 to model space 1
   PointClass d0, d1, d2;
   m_M0ToM1.mult(p0->getPosition(0), d0);
   m_M0ToM1.mult(p0->getPosition(1), d1);
   m_M0ToM1.mult(p0->getPosition(2), d2);

   if (!g1->getBVol().checkIntersect(d0, d1, d2)) {
      return DoubleTraverserBase<BasicTraits>::QUIT;
   }
#endif
   return DoubleTraverserBase<BasicTraits>::CONTINUE;
}
typename BVolCollision<BasicTraits,BVOL>::ResultT
BVolCollision<BasicTraits,BVOL>::PrimPrimCollision 
(AdapterType* p0, AdapterType* p1)
{
   ++m_numPrimPrimTests;
#if defined(GV_BVOLS_IN_MIXEDTESTS)
   Real t = (this->*f_primIntersect)(p0, p1);
   if (t >= 0.0f) {
      // Keep track of colliding pairs
      // check if first collision already found
      if (!getStopFirst() || getNumContacts() == 0) {
	 m_contacts.push_back(CollisionPair(p0, p1));
	 CollisionInterface<OpenSGTriangleBase<BasicTraits>,Real> 
	   result(m_contacts[m_contacts.size()-1]);
	 result.getData() = t;
      }
      CollisionInterface<OpenSGTriangleBase<BasicTraits>,Real> 
	result(m_contacts[0]);
      if (t < result.getData()) {
	 result.getData() = t;
	 m_contacts[0].setFirst(p0);
	 m_contacts[0].setSecond(p1);
      }
   }
#else
   // Transform from model space 1 to model space 0
   PointClass d0, d1, d2;
   m_M1ToM0.mult(p1->getPosition(0), d0);
   m_M1ToM0.mult(p1->getPosition(1), d1);
   m_M1ToM0.mult(p1->getPosition(2), d2);

   // Perform triangle-triangle overlap test
   if (genvis::triTriOverlap(p0->getPosition(0), 
			     p0->getPosition(1), 
			     p0->getPosition(2), 
			     d0, 
			     d1, 
			     d2)) {
      // Keep track of colliding pairs
      m_contacts.push_back(CollisionPair(p0, p1));
   }
#endif
   return DoubleTraverserBase<BasicTraits>::CONTINUE;
}
Пример #12
0
int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const
{
	btScalar shortestDist =  getContactBreakingThreshold() * getContactBreakingThreshold();
	int size = getNumContacts();
	int nearestPoint = -1;
	for( int i = 0; i < size; i++ )
	{
		const btManifoldPoint &mp = m_pointCache[i];

		btVector3 diffA =  mp.m_localPointA- newPoint.m_localPointA;
		const btScalar distToManiPoint = diffA.dot(diffA);
		if( distToManiPoint < shortestDist )
		{
			shortestDist = distToManiPoint;
			nearestPoint = i;
		}
	}
	return nearestPoint;
}
Пример #13
0
        void ConstraintDynamics::applySolution() {
            VectorXd contactForces(VectorXd::Zero(getTotalNumDofs()));
            VectorXd jointLimitForces(VectorXd::Zero(getTotalNumDofs()));

            if (getNumContacts() > 0) {
                VectorXd f_n = mX.head(getNumContacts());
                VectorXd f_d = mX.segment(getNumContacts(), getNumContacts() * mNumDir);
                contactForces.noalias() = mN * f_n;
                contactForces.noalias() += mB * f_d;
                for (int i = 0; i < getNumContacts(); i++) {
                    Contact& contact = mCollisionChecker->getContact(i);
                    contact.force.noalias() = getTangentBasisMatrix(contact.point, contact.normal) * f_d.segment(i * mNumDir, mNumDir);
                    contact.force.noalias() += contact.normal * f_n[i];
                }
            }
            for (int i = 0; i < mLimitingDofIndex.size(); i++) {
                if (mLimitingDofIndex[i] > 0) { // hitting upper bound
                    jointLimitForces[mLimitingDofIndex[i] - 1] = -mX[getNumContacts() * (2 + mNumDir) + i];
                }else{
                    jointLimitForces[abs(mLimitingDofIndex[i]) - 1] = mX[getNumContacts() * (2 + mNumDir) + i];
                }
            }
            
            VectorXd lambda = VectorXd::Zero(mGInv.rows());
            for (int i = 0; i < mSkels.size(); i++) {
                if (mSkels[i]->getImmobileState())
                    continue;
                mContactForces[i] = contactForces.segment(mIndices[i], mSkels[i]->getNumDofs());

                mTotalConstrForces[i] = mContactForces[i] + jointLimitForces.segment(mIndices[i], mSkels[i]->getNumDofs());
                
                if (mConstraints.size() > 0) {
                    VectorXd tempVec = mGInv * (mTauHat - mJMInv[i] * (contactForces.segment(mIndices[i], mSkels[i]->getNumDofs()) + jointLimitForces.segment(mIndices[i], mSkels[i]->getNumDofs())));
                    mTotalConstrForces[i] += mJ[i].transpose() * tempVec;
                    lambda += tempVec;
                }
            }

            int count = 0;
            for (int i = 0; i < mConstraints.size(); i++) {
                mConstraints[i]->setLagrangeMultipliers(lambda.segment(count, mConstraints[i]->getNumRows()));
                count += mConstraints[i]->getNumRows();
            }
            
        }
Пример #14
0
MatrixXd ContactDynamics::getMuMatrix() const {
    int c = getNumContacts();
    // TESTING CODE BEGIN (create a frictionless node)
    /*        MatrixXd mat(MatrixXd::Identity(c, c));
            double mu;
            for (int i = 0; i < c; i++) {
                ContactPoint& contact = mCollisionChecker->getContact(i);
                if (contact.bdID1 == 0 || contact.bdID2 == 0)
                    mu = 0.0;
                else
                    mu = mMu;
                mat(i, i) = mu;
            }
            return mat / (mDt * mDt);
            // TESTING CODE END
            */
    //        return (MatrixXd::Identity(c, c) * mMu / (mDt * mDt));
    return MatrixXd::Identity(c, c) * mMu;

}
Пример #15
0
        void ConstraintDynamics::fillMatrices() {
            int nContacts = getNumContacts();
            int nJointLimits = mLimitingDofIndex.size();
            int nConstrs = mConstraints.size();
            int cd = nContacts * mNumDir;
            int dimA = nContacts * (2 + mNumDir) + nJointLimits;
            mA = MatrixXd::Zero(dimA, dimA);
            mQBar = VectorXd::Zero(dimA);
            updateMassMat();
            updateTauStar();
            
            MatrixXd augMInv = mMInv;
            VectorXd tauVec = VectorXd::Zero(getTotalNumDofs());
            if (nConstrs > 0) {
                updateConstraintTerms();
                augMInv -= mZ;

                VectorXd tempVec = mDt * mGInv * mTauHat;
                for (int i = 0; i < mSkels.size(); i++) {
                    if (mSkels[i]->getImmobileState())
                        continue;
                    tauVec.segment(mIndices[i], mSkels[i]->getNumDofs()) = mJ[i].transpose() * tempVec;
                }
            }
            tauVec = mMInv * (tauVec + mTauStar);

            MatrixXd Ntranspose(nContacts, getTotalNumDofs());
            MatrixXd Btranspose(cd, getTotalNumDofs());
            MatrixXd NTerm(getTotalNumDofs(), nContacts);
            MatrixXd BTerm(getTotalNumDofs(), cd);

            if (nContacts > 0) {
                updateNBMatrices();
                MatrixXd E = getContactMatrix();
                MatrixXd mu = getMuMatrix();
                // Construct the intermediary blocks.
                Ntranspose = mN.transpose();
                Btranspose = mB.transpose();
                // Compute NTerm and BTerm
                NTerm = augMInv * mN;
                BTerm = augMInv * mB;
                mA.block(0, 0, nContacts, nContacts) = Ntranspose * NTerm;
                mA.block(0, nContacts, nContacts, cd) = Ntranspose * BTerm;
                mA.block(nContacts, 0, cd, nContacts) = Btranspose * NTerm;
                mA.block(nContacts, nContacts, cd, cd) = Btranspose * BTerm;
                mA.block(nContacts, nContacts + cd, cd, nContacts) = E;
                mA.block(nContacts + cd, 0, nContacts, nContacts) = mu;
                mA.block(nContacts + cd, nContacts, nContacts, cd) = -E.transpose();

                mQBar.segment(0, nContacts) = Ntranspose * tauVec;
                mQBar.segment(nContacts, cd) = Btranspose * tauVec;

            }

            if (nJointLimits > 0) {
                int jointStart = 2 * nContacts + cd;
                for (int i = 0; i < nJointLimits; i++)
                    for (int j = 0; j < nJointLimits; j++) {
                        if (mLimitingDofIndex[i] * mLimitingDofIndex[j] < 0)
                            mA(jointStart + i, jointStart + j) = -augMInv(abs(mLimitingDofIndex[i]) - 1, abs(mLimitingDofIndex[j]) - 1);
                        else
                            mA(jointStart + i, jointStart + j) = augMInv(abs(mLimitingDofIndex[i]) - 1, abs(mLimitingDofIndex[j]) - 1);
                    }
                for (int i = 0; i < nJointLimits; i++) {
                    if (mLimitingDofIndex[i] > 0) // hitting upper bound
                        mQBar[jointStart + i] = -tauVec[abs(mLimitingDofIndex[i]) - 1];
                    else // hitting lower bound
                        mQBar[jointStart + i] = tauVec[abs(mLimitingDofIndex[i]) - 1];
                }

                if (nContacts > 0) {

                    MatrixXd STerm(mMInv.rows(), nJointLimits);
                    for (int i = 0; i < nJointLimits; i++) {
                        if (mLimitingDofIndex[i] > 0) // hitting upper bound
                            STerm.col(i) = -augMInv.col(mLimitingDofIndex[i] - 1);
                        else                            
                            STerm.col(i) = augMInv.col(abs(mLimitingDofIndex[i]) - 1);
                    }
                    mA.block(0, jointStart, nContacts, nJointLimits) = Ntranspose * STerm;

                    mA.block(nContacts, jointStart, cd, nJointLimits) = Btranspose * STerm;

                    for (int i = 0; i < nJointLimits; i++) {
                        if (mLimitingDofIndex[i] > 0) { //hitting uppder bound
                            mA.block(jointStart + i, 0, 1, nContacts) = -NTerm.row(mLimitingDofIndex[i] - 1);
                            mA.block(jointStart + i, nContacts, 1, cd) = -BTerm.row(mLimitingDofIndex[i] - 1);
                        } else {
                            mA.block(jointStart + i, 0, 1, nContacts) = NTerm.row(abs(mLimitingDofIndex[i]) - 1);
                            mA.block(jointStart + i, nContacts, 1, cd) = BTerm.row(abs(mLimitingDofIndex[i]) - 1);
                        }
                    }

                }
            }
            mQBar /= mDt;
            
            int cfmSize = getNumContacts() * (1 + mNumDir);
            for (int i = 0; i < cfmSize; ++i) //add small values to diagnal to keep it away from singular, similar to cfm varaible in ODE
                mA(i, i) += 0.001 * mA(i, i);
        }
Пример #16
0
        MatrixXd ConstraintDynamics::getMuMatrix() const {
            int c = getNumContacts();
            return MatrixXd::Identity(c, c) * mMu;

        }
Пример #17
0
bool ContactDynamics::solve() {
    lcpsolver::LCPSolver solver = lcpsolver::LCPSolver();
    bool b = solver.Solve(mA, mQBar, mX, getNumContacts(), mMu, mNumDir, true);
    return b;
}
Пример #18
0
void ContactDynamics::fillMatrices() {
    updateTauStar();

    updateNBMatrices();
    //        updateNormalMatrix();
    //        updateBasisMatrix();

    MatrixXd E = getContactMatrix();

    int c = getNumContacts();
    int cd = c * mNumDir;

    // Construct the intermediary blocks.
    // nTmInv = mN.transpose() * MInv
    // bTmInv = mB.transpose() * MInv
    // Where MInv is the imaginary diagonal block matrix that combines the inverted mass matrices of all skeletons.
    // Muliplying each block independently is more efficient that multiplyting the whole MInv matrix.
    MatrixXd nTmInv(c, getNumTotalDofs());
    MatrixXd bTmInv(cd, getNumTotalDofs());
    for (int i = 0; i < getNumSkels(); i++) {
        if (mSkels[i]->getImmobileState()) {
            assert(mIndices[i] == mIndices[i+1]); // If the user sets a skeleton to be immobile without reinitializing ContactDynamics, this assertion will fail.
            continue;
        }
        const MatrixXd skelMInv = mSkels[i]->getInvMassMatrix();
        const int skelNumDofs = mSkels[i]->getNumDofs();
        nTmInv.middleCols(mIndices[i], skelNumDofs).noalias() = mN.transpose().middleCols(mIndices[i], skelNumDofs) * skelMInv;
        bTmInv.middleCols(mIndices[i], skelNumDofs).noalias() = mB.transpose().middleCols(mIndices[i], skelNumDofs) * skelMInv;
    }

    // Construct
    int dimA = c * (2 + mNumDir); // dimension of A is c + cd + c
    mA.resize(dimA, dimA);
    mA.topLeftCorner(c, c).triangularView<Upper>() = nTmInv * mN;
    mA.topLeftCorner(c, c).triangularView<StrictlyLower>() = mA.topLeftCorner(c, c).transpose();
    mA.block(0, c, c, cd).noalias() = nTmInv * mB;
    mA.block(c, 0, cd, c) = mA.block(0, c, c, cd).transpose(); // since B^T * Minv * N = (N^T * Minv * B)^T
    mA.block(c, c, cd, cd).triangularView<Upper>() = bTmInv * mB;
    mA.block(c, c, cd, cd).triangularView<StrictlyLower>() = mA.block(c, c, cd, cd).transpose();
    //        mA.block(c, c + cd, cd, c) = E * (mDt * mDt);
    mA.block(c, c + cd, cd, c) = E;
    //        mA.block(c + cd, 0, c, c) = mu * (mDt * mDt);
    mA.bottomLeftCorner(c, c) = getMuMatrix(); // Note: mu is a diagonal matrix, but we also set the surrounding zeros
    //        mA.block(c + cd, c, c, cd) = -E.transpose() * (mDt * mDt);
    mA.block(c + cd, c, c, cd) = -E.transpose();
    mA.topRightCorner(c, c).setZero();
    mA.bottomRightCorner(c, c).setZero();

    int cfmSize = getNumContacts() * (1 + mNumDir);
    for (int i = 0; i < cfmSize; ++i) //add small values to diagnal to keep it away from singular, similar to cfm varaible in ODE
        mA(i, i) += 0.001 * mA(i, i);

    // Construct Q
    mQBar = VectorXd::Zero(dimA);

    /*
            VectorXd MinvTauStar(mN.rows());
            int rowStart = 0;
            for (int i = 0; i < mSkels.size(); i++) {
                int nDof = mSkels[i]->getNumDofs();
                if (mSkels[i]->getImmobileState()) {
                    continue;
                } else {
                    MinvTauStar.segment(rowStart, nDof) = mMInv.block(rowStart, rowStart, nDof, nDof) * mTauStar.segment(rowStart, nDof);
                }
                rowStart += nDof;
            }
            */
    //mQBar.block(0, 0, c, 1) = mN.transpose() * MinvTauStar;
    //mQBar.block(c, 0, cd, 1) = mB.transpose() * MinvTauStar;

    mQBar.head(c).noalias() = nTmInv * mTauStar;
    mQBar.segment(c,cd).noalias() = bTmInv * mTauStar;
    mQBar /= mDt;
}
typename PrecomputedAlignCollision<BasicTraits,BVOL>::ResultT
PrecomputedAlignCollision<BasicTraits,BVOL>::BVolPrimCollision (GroupType* g0, AdapterType* p1)
{
    // check if first collision already found
    if (getStopFirst() && getNumContacts()>0) {
        return DoubleTraverserBase<BasicTraits>::QUIT;
    }
    ++m_numBVolPrimTests;
#if 0
    // perform BV-BV overlap test
    const BVOL& dop1 = g0->getBVol();
    const BVOL& dop2 = p1->getBVol();
    const Real* center = p1->getData().getRotationCenter();

    u32   k, kk, mink, maxk;
    Real       min2, max2, correct;
    for (k=0, kk=BVOL::Size; k<BVOL::Size; ++k, ++kk) {
        maxk = m_perm[k];
        mink = m_perm[kk];

        if (maxk < BVOL::Size) {
            max2 =  dop2.maxVector()[maxk] - center[maxk];
            min2 =  dop2.minVector()[maxk] - center[maxk];
        } else {
            max2 = -dop2.minVector()[mink] + center[mink];
            min2 = -dop2.maxVector()[mink] + center[mink];
        }
        min2 *= m_scale;
        max2 *= m_scale;
        correct = m_proj[k].dot(p1->getCenter());
#ifdef GV_WITH_SUBCONES
        min2 = min2*BVOL::unitDopAngleTable(p1->getData().getOccupancy(mink)[m_submask[kk]],
                                            m_mask[kk],
                                            p1->getData().getOuterMost(mink)[m_submask[kk]])
               + correct;
        max2 = max2*BVOL::unitDopAngleTable(p1->getData().getOccupancy(maxk)[m_submask[k]],
                                            m_mask[k],
                                            p1->getData().getOuterMost(maxk)[m_submask[k]])
               + correct;
#else
        min2 = min2*BVOL::unitDopAngleTable(p1->getData().getOccupancy(mink)[0],
                                            m_mask[kk],
                                            p1->getData().getOuterMost(mink)[0])
               + correct;
        max2 = max2*BVOL::unitDopAngleTable(p1->getData().getOccupancy(maxk)[0],
                                            m_mask[k],
                                            p1->getData().getOuterMost(maxk)[0])
               + correct;
#endif
        if (stdMin(dop1.maxVector()[k], max2+m_M1Offset[k]) < stdMax(dop1.minVector()[k], min2+m_M1Offset[k])) {
            return DoubleTraverserBase<BasicTraits>::QUIT;
        }
    }
#else
    // Transform from model space 1 to model space 0
    PointClass d0, d1, d2;
    m_M1ToM0.mult(p1->getPosition(0), d0);
    m_M1ToM0.mult(p1->getPosition(1), d1);
    m_M1ToM0.mult(p1->getPosition(2), d2);

    if (!g0->getBVol().checkIntersect(d0, d1, d2)) {
        return DoubleTraverserBase<BasicTraits>::QUIT;
    }
#endif
    return DoubleTraverserBase<BasicTraits>::CONTINUE;
}
Пример #20
0
        void ContactDynamics::fillMatrices() {
            updateMassMat();
            updateTauStar();

            updateNBMatrices();
            //        updateNormalMatrix();
            //        updateBasisMatrix();

            MatrixXd E = getContactMatrix();
            MatrixXd mu = getMuMatrix();

            // Construct the intermediary blocks.
            MatrixXd Ntranspose = mN.transpose();
            MatrixXd Btranspose = mB.transpose();
            MatrixXd nTmInv = Ntranspose * mMInv;
            MatrixXd bTmInv = Btranspose * mMInv;

            // Construct
            int c = getNumContacts();
            int cd = c * mNumDir;
            int dimA = c * (2 + mNumDir); // dimension of A is c + cd + c
            mA.resize(dimA, dimA);
            mA.topLeftCorner(c, c) = nTmInv * mN;
            mA.block(0, c, c, cd) = nTmInv * mB;
            mA.block(c, 0, cd, c) = bTmInv * mN;
            mA.block(c, c, cd, cd) = bTmInv * mB;
            //        mA.block(c, c + cd, cd, c) = E * (mDt * mDt);
            mA.block(c, c + cd, cd, c) = E;
            //        mA.block(c + cd, 0, c, c) = mu * (mDt * mDt);
            mA.bottomLeftCorner(c, c) = mu; // Note: mu is a diagonal matrix, but we also set the surrounding zeros
            //        mA.block(c + cd, c, c, cd) = -E.transpose() * (mDt * mDt);
            mA.block(c + cd, c, c, cd) = -E.transpose();
            mA.topRightCorner(c, c).setZero();
            mA.bottomRightCorner(c, c).setZero();

            int cfmSize = getNumContacts() * (1 + mNumDir);
            for (int i = 0; i < cfmSize; ++i) //add small values to diagnal to keep it away from singular, similar to cfm varaible in ODE
                mA(i, i) += 0.001 * mA(i, i);

            // Construct Q
            mQBar = VectorXd::Zero(dimA);

            /*
            VectorXd MinvTauStar(mN.rows());
            int rowStart = 0;
            for (int i = 0; i < mSkels.size(); i++) {
                int nDof = mSkels[i]->getNumDofs();
                if (mSkels[i]->getImmobileState()) {
                    continue;
                } else {
                    MinvTauStar.segment(rowStart, nDof) = mMInv.block(rowStart, rowStart, nDof, nDof) * mTauStar.segment(rowStart, nDof);
                }
                rowStart += nDof;
            }
            */
            //mQBar.block(0, 0, c, 1) = Ntranspose * MinvTauStar;
            //mQBar.block(c, 0, cd, 1) = Btranspose * MinvTauStar;

            mQBar.head(c) = nTmInv * mTauStar;
            mQBar.segment(c,cd) = bTmInv * mTauStar;
            mQBar /= mDt;
        }