Example #1
0
void DContact::ResolveCollisions(const float2& Ncoll, float t, float fCoF, float fCoR,
					  const float2& C0, const float2& P0, float2& V0, float& w0, float m0, float i0, 
					  const float2& C1, const float2& P1, float2& V1, float& w1, float m1, float i1)
{
	// pre-computations
	float tcoll = t > 0.0f ? t : 0.0f;

	float2 Q0 = P0 + V0 * tcoll;
	float2 Q1 = P1 + V1 * tcoll;
	float2 R0 = C0 - Q0;
	float2 R1 = C1 - Q1;
	float2 T0(-R0.y, R0.x);
	float2 T1(-R1.y, R1.x);
	float2 VP0 = V0 - T0 * w0;
	float2 VP1 = V1 - T1 * w1;

	// impact velocity
	float2 Vcoll = VP0 - VP1;
	float  vn	 = Vcoll.dot(Ncoll);
	float2 Vn	 = Ncoll * vn;
	float2 Vt	 = Vcoll - Vn;
	if(vn > 0.0f) { return; }
	float vt = Vt.magnitude();
	Vt = Vt.normalize();

	// compute impulse (friction and restitution)
	float2 J, Jt(0.0f, 0.0f), Jn(0.0f, 0.0f);
	float t0 = (R0 ^ Ncoll) * (R0 ^ Ncoll) * i0;
	float t1 = (R1 ^ Ncoll) * (R1 ^ Ncoll) * i1;
	float m  = m0 + m1;
	float denom = m + t0 + t1;
	float jn = vn / denom;
	Jn = Ncoll * (-(1.0f + fCoR) * jn); // restitution
	Jt = Vt.normalize() * (fCoF * jn); // friction
	J = Jn + Jt;

	// changes in momentum
	float2 dV0 = J * m0;
	float2 dV1 = -J * m1;
	float dw0 =-(R0 ^ J) * i0; 
	float dw1 = (R1 ^ J) * i1;

	if(m0 > 0.0f) { V0 += dV0; w0 += dw0; }; // apply changes in momentum
	if(m1 > 0.0f) { V1 += dV1; w1 += dw1; }; // apply changes in momentum

	// Check for static frcition
	if (vn < 0.0f && fCoF > 0.0f)
	{
		float cone = -vt / vn;
		if (cone < fCoF)
		{
			float2 Nfriction = -Vt.normalize();
			float fCoS = cmat.coStaticFriction;

			ResolveCollisions(Nfriction, 0.0f, 0.0f, fCoS,
							 C0, P0, V0, w0, m0, i0, 
							 C1, P1, V1, w1, m1, i1);
		}
	}
};
Example #2
0
MatrixXd ContactDynamics::getJacobian(kinematics::BodyNode* node, const Vector3d& p) {
    int nDofs = node->getSkel()->getNumDofs();
    MatrixXd Jt( MatrixXd::Zero(nDofs, 3) );
    Vector3d invP = dart_math::xformHom(node->getWorldInvTransform(), p);

    for(int dofIndex = 0; dofIndex < node->getNumDependentDofs(); dofIndex++) {
        int i = node->getDependentDof(dofIndex);
        Jt.row(i) = dart_math::xformHom(node->getDerivWorldTransform(dofIndex), invP);
    }

    return Jt;
}
Example #3
0
////////////////////////////////////////////////////////////////
// ResolveCollision
////////////////////////////////////////////////////////////////
// calculates the change in angular and linear velocity of two
// colliding objects
////////////////////////////////////////////////////////////////
// parameters :
// ------------
// Ncoll : normal of collision
// t : time of collision, (if negative, it's a penetration depth)
// fCoF : coefficient of friction
// fCoR : coefficient of restitution
// C0 : point of contact on object 0
// P0 : centre of gravity (position) of object 0
// V0 : linear Velocity of object 0
// w0 : angular velocity of object 0
// m0 : inverse mass of object 0
// i0 : inverse inertia of object 0
// C1 : point of contact on object 1
// P1 : centre of gravity (position) of object 1
// V1 : linear Velocity of object 1
// w1 : angular velocity of object 1
// m1 : inverse mass of object 1
// i1 : inverse inertia of object 1
//
// return values : V0, w0, V1, w1 will change upon a collision
// -------------
///////////////////////////////////////////////////////////////
void ResolveCollision(const glm::vec2& Ncoll, float t, float fCoF, float fCoR,
					  const glm::vec2& C0, const glm::vec2& P0, glm::vec2& V0, float& w0, float m0, float i0,
					  const glm::vec2& C1, const glm::vec2& P1, glm::vec2& V1, float& w1, float m1, float i1)
{
	//------------------------------------------------------------------------------------------------------
	// pre-computations
	//------------------------------------------------------------------------------------------------------
	float tcoll = (t > 0.0f)? t : 0.0f;

	glm::vec2 Q0    = P0 + V0 * tcoll;
	glm::vec2 Q1    = P1 + V1 * tcoll;
	glm::vec2 R0    = C0 - Q0;
	glm::vec2 R1    = C1 - Q1;
	glm::vec2 T0    = glm::vec2(-R0.y, R0.x);
	glm::vec2 T1    = glm::vec2(-R1.y, R1.x);
	glm::vec2 VP0   = V0 - T0 * w0; // point velocity (SIGN IS WRONG)
	glm::vec2 VP1   = V1 - T1 * w1; // point velocity (SIGN IS WRONG)

	//------------------------------------------------------------------------------------------------------
	// impact velocity
	//------------------------------------------------------------------------------------------------------
	glm::vec2 Vcoll = VP0 - VP1;
	float  vn	 = glm::dot(Vcoll, Ncoll);
	glm::vec2 Vn	 = vn    * Ncoll;
	glm::vec2 Vt	 = Vcoll - Vn;

	// separation
	if (vn > 0.0f)
		return;

	float  vt = glm::length(Vt);


	//------------------------------------------------------------------------------------------------------
	// compute impulse (frction and restitution).
	// ------------------------------------------
	//
	//									-(1+Cor)(Vel.norm)
	//			j =  ------------------------------------------------------------
	//			     [1/Ma + 1/Mb] + [Ia' * (ra x norm)²] + [Ib' * (rb x norm)²]
	//------------------------------------------------------------------------------------------------------
	glm::vec2 J;
	glm::vec2 Jt(0.0f, 0.0f);
	glm::vec2 Jn(0.0f, 0.0f);

	float t0 = cross(R0, Ncoll) * cross(R0, Ncoll) * i0;
	float t1 = cross(R1, Ncoll) * cross(R1, Ncoll) * i1;
	float m  = m0 + m1;

	float denom = m + t0 + t1;

	float jn = vn / denom;

	Jn = (-(1.0f + fCoR) * jn) * Ncoll;

	if (dbg_UseFriction)
	{
		Jt = (fCoF * jn) * glm::normalize(Vt);
	}

	J = Jn + Jt;

	//------------------------------------------------------------------------------------------------------
	// changes in momentum
	//------------------------------------------------------------------------------------------------------
	glm::vec2 dV0 = J * m0;
	glm::vec2 dV1 =-J * m1;

	float dw0 =-cross(R0, J) * i0; // (SIGN IS WRONG)
	float dw1 = cross(R1, J) * i1; // (SIGN IS WRONG)

	//------------------------------------------------------------------------------------------------------
	// apply changes in momentum
	//------------------------------------------------------------------------------------------------------
	if (m0 > 0.0f) V0 += dV0;
	if (m1 > 0.0f) V1 += dV1;
	if (m0 > 0.0f) w0 += dw0;
	if (m1 > 0.0f) w1 += dw1;

	//------------------------------------------------------------------------------------------------------
	// Check for static frcition
	//------------------------------------------------------------------------------------------------------
	if (vn < 0.0f && fCoF > 0.0f)
	{
		float cone = -vt / vn;

		if (cone < fCoF)
		{
			// treat static friciton as a collision at the contact point
			glm::vec2 Nfriction = glm::normalize(-Vt);
			float fCoS = GetStaticFriction;

			ResolveCollision(Nfriction, 0.0f, 0.0f, fCoS,
							 C0, P0, V0, w0, m0, i0,
							 C1, P1, V1, w1, m1, i1);
		}
	}
}
Example #4
0
    void Contact::ResolveCollision()
    {
        if (!m_pxBodies[0] || !m_pxBodies[1])
            return;

        //------------------------------------------------------------------------------------------------------
        // parameters
        //------------------------------------------------------------------------------------------------------
        Point2f C0    = m_xContacts[0];
        Point2f C1    = m_xContacts[1];
        Point2f Ncoll = C1 - C0;
        // assert(Ncoll.x != 0 || Ncoll.y != 0);
        Ncoll.Normalize();

        float m0 = m_pxBodies[0]->getInvMass();
        float m1 = m_pxBodies[1]->getInvMass();
        float i0 = m_pxBodies[0]->getInvInertia();
        float i1 = m_pxBodies[1]->getInvInertia();

        const Point2f& P0   = m_pxBodies[0]->getPosition();
        const Point2f& P1   = m_pxBodies[1]->getPosition();
        const Point2f& V0   = m_pxBodies[0]->getVelocity();
        const Point2f& V1   = m_pxBodies[1]->getVelocity();
        float  w0   = m_pxBodies[0]->getAngVelocity();
        float  w1   = m_pxBodies[1]->getAngVelocity();

        //------------------------------------------------------------------------------------------------------
        // pre-computations
        //------------------------------------------------------------------------------------------------------
        Point2f R0    = C0 - P0;
        Point2f R1    = C1 - P1;
        Point2f T0    = Point2f(-R0.y, R0.x);
        Point2f T1    = Point2f(-R1.y, R1.x);
        Point2f VP0   = V0 + T0 * w0; // point velocity
        Point2f VP1   = V1 + T1 * w1; // point velocity

        //------------------------------------------------------------------------------------------------------
        // impact velocity
        //------------------------------------------------------------------------------------------------------
        Point2f Vcoll = VP0 - VP1;
        float  vn	 = Vcoll * Ncoll;
        Point2f Vn	 = Ncoll * vn;
        Point2f Vt	 = Vcoll - Vn;

        if (vn > 0.0f) // separation
            return;

        if (Vt * Vt < 0.0001f)
            Vt = Point2f(0.0f, 0.0f);

        // float  vt = Vt.Length();
        Vt.Normalize();


        //------------------------------------------------------------------------------------------------------
        // compute impulse (frction and restitution).
        // ------------------------------------------
        //
        //									-(1+Cor)(Vel.norm)
        //			j =  ------------------------------------------------------------
        //			     [1/Ma + 1/Mb] + [Ia' * (ra x norm)²] + [Ib' * (rb x norm)²]
        //------------------------------------------------------------------------------------------------------
        Point2f J;
        Point2f Jt(0.0f, 0.0f);
        Point2f Jn(0.0f, 0.0f);

        float fCoR  = s_xContactMaterial.GetRestitution();
        float fCoF  = s_xContactMaterial.GetFriction();

        float t0 = (R0 ^ Ncoll) * (R0 ^ Ncoll) * i0;
        float t1 = (R1 ^ Ncoll) * (R1 ^ Ncoll) * i1;
        float m  = m0 + m1;

        float denom = m + t0 + t1;

        float jn = vn / denom;

        Jn = Ncoll * (-(1.0f + fCoR) * jn);

        //if (dbg_UseFriction)
        Jt = Vt * (fCoF * jn);

        J = Jn + Jt;

        //------------------------------------------------------------------------------------------------------
        // changes in momentum
        //------------------------------------------------------------------------------------------------------
        Point2f dV0 = J * m0;
        Point2f dV1 =-J * m1;

        float dw0 = (R0 ^ J) * i0;
        float dw1 =-(R1 ^ J) * i1;

        //------------------------------------------------------------------------------------------------------
        // apply changes in momentum
        //------------------------------------------------------------------------------------------------------
        if (!m_pxBodies[0]->isStaticBody())
        {
            if (m0 > 0.0f)
            {
                m_pxBodies[0]->setVelocity(V0 + dV0);
            }
            if (m0 > 0.0f)
            {
                m_pxBodies[0]->setAngVelocity(w0 + dw0);
            }
        }
        if (!m_pxBodies[1]->isStaticBody())
        {
            if (m1 > 0.0f)
            {
                m_pxBodies[1]->setVelocity(V1 + dV1);
            }
            if (m1 > 0.0f)
            {
                m_pxBodies[1]->setAngVelocity(w1 + dw1);
            }
        }
        //	Render();
        return;
/*
        //------------------------------------------------------------------------------------------------------
        // Check for static frcition
        //------------------------------------------------------------------------------------------------------
        float fRestingContactVelocity = 1.0f;

        if (-vn < fRestingContactVelocity)
        {
            if (vt < fRestingContactVelocity * fCoF)
            {
                //------------------------------------------------------------------------------------------------------
                // Cancel tangential velocity on the two bodies, so they stick
                //------------------------------------------------------------------------------------------------------
                Point2f dV = V1 - V0;
                dV -= Ncoll * (dV * Ncoll);
                if (m0 > 0.0f) V0 += dV * (m0 / m + 0.01f);
                if (m1 > 0.0f) V1 -= dV * (m1 / m + 0.01f);
            }
        }
        */
    }
Example #5
0
File: lm.cpp Project: caomw/r4r
CDenseVector<T> CLevenbergMarquardt<Matrix,T>::Iterate(size_t n, T epsilon1, T epsilon2, bool silent) {

	// access to state
    CDenseVector<T>& x = m_problem.Get();

	// initial residual, Jacobian
    CDenseVector<T> r(m_problem.GetNumberOfDataPoints());
    Matrix J(m_problem.GetNumberOfDataPoints(),m_problem.GetNumberOfModelParameters());
	m_problem.ComputeResidualAndJacobian(r,J);

    // initial value for lambda, TODO: do this depending on trace of J'*J
	m_lambda = m_tau*1;

    // residual norm
    T res = r.Norm2();
    m_residuals.push_back(res);

	// gradient norm
	J.Transpose();
    CDenseVector<T> grad = J*r;
	J.Transpose();
    T normgrad = grad.Norm2();

	// init other quantities
    T nu = m_params[2];
	size_t k = 0;

	// in verbose mode, print out initial residual, etc.
	if(!silent) {

		cout.setf(ios::scientific,ios::floatfield);

		cout << "k\t f(x)\t ||grad f||\t ||h||\t lambda" << endl;
		cout << k << "\t" << res << "\t" << normgrad << "\t" << 0.0000 << "\t" << m_lambda << endl;

	}

	while(true) {

        // solve linear system after setting lmbda in the CGLS solver
        CDenseVector<T> step(m_problem.GetNumberOfModelParameters());
        m_solver.SetLambda(sqrt(m_lambda));
        m_solver.Iterate(J,r,step);

        // save old state before advancing
        CDenseVector<T> xold = x.Clone();

        // tentative point, everything is allocated so changing pointer is ok
        x = x - step;

        // compute tentative residual and Jacobian
        CDenseVector<T> rt(m_problem.GetNumberOfDataPoints());
        Matrix Jt(m_problem.GetNumberOfDataPoints(),m_problem.GetNumberOfModelParameters());
        m_problem.ComputeResidualAndJacobian(rt,Jt);

        // residual norm
        res = rt.Norm2();

		// compute rho
        T normstep, descent, dres, dlres, rho;
		dres = m_residuals.back() - res;

        normstep = sqrt(CDenseVector<T>::InnerProduct(step,step));
        descent = -CDenseVector<T>::InnerProduct(step,grad);

        dlres = 0.5*(normstep*normstep*m_lambda - descent);
		rho = dres/dlres;

		// check step size criterion (lambda going to infinity)
		if(normstep<epsilon2*xold.Norm2())
            break;

		// update state if a descent direction is found
        if(rho>0) {

			// it ok now to store the residual norm
			m_residuals.push_back(res);

            // keep Jacobian and residual, should be ok to move pointers
            r = rt;
            J = Jt;

            // update gradient norm, this contains step size parameter (but maybe it should not?)
            J.Transpose();
            grad = J*r;
            J.Transpose();
			normgrad = grad.Norm2();

			// push lambda towards Gauss-Newton step
			nu = m_params[2];
            T factor = max(m_params[3],1-(m_params[2]-1)*pow(2*rho-1,m_params[5]));
            m_lambda *= factor;

			k++;

			// print out current state of optimization
			if(!silent)
                cout << k << "\t" << res << "\t" << normgrad << "\t" << normstep << "\t" << m_lambda << endl;

			// check convergence criteria
            if(normgrad<epsilon1 || k==n)
				break;

        }
		else {

			// push towards gradient descent
			if(m_lambda>0)
				m_lambda *= nu;
			else
				m_lambda = 1e-12;

			nu *= 2;

			// restore state because step was unsuccessful
            x = xold;

            // show how lambda develops
            if(!silent)
                cout << "Adjusting lambda to " << m_lambda << "." << endl;

        }

        if(std::isinf(m_lambda))
            break;

	}

	return r;

}