Пример #1
0
dgJacobian dgDynamicBody::IntegrateForceAndToque(const dgVector& force, const dgVector& torque, const dgVector& timestep)
{
	dgJacobian velocStep;
	if (m_gyroTorqueOn) {
		dgVector dtHalf(timestep * dgVector::m_half);
		dgMatrix matrix(m_gyroRotation, dgVector::m_wOne);

		dgVector localOmega(matrix.UnrotateVector(m_omega));
		dgVector localTorque(matrix.UnrotateVector(torque - m_gyroTorque));

		// derivative at half time step. (similar to midpoint Euler so that it does not loses too much energy)
		dgVector dw(localOmega * dtHalf);
		dgMatrix jacobianMatrix(
			dgVector(m_mass[0], (m_mass[2] - m_mass[1]) * dw[2], (m_mass[2] - m_mass[1]) * dw[1], dgFloat32(0.0f)),
			dgVector((m_mass[0] - m_mass[2]) * dw[2], m_mass[1], (m_mass[0] - m_mass[2]) * dw[0], dgFloat32(1.0f)),
			dgVector((m_mass[1] - m_mass[0]) * dw[1], (m_mass[1] - m_mass[0]) * dw[0], m_mass[2], dgFloat32(1.0f)),
			dgVector::m_wOne);

		// and solving for alpha we get the angular acceleration at t + dt
		// calculate gradient at a full time step
		//dgVector gradientStep(localTorque * timestep);
		dgVector gradientStep(jacobianMatrix.SolveByGaussianElimination(localTorque * timestep));

		dgVector omega(matrix.RotateVector(localOmega + gradientStep));
		dgAssert(omega.m_w == dgFloat32(0.0f));

		// integrate rotation here
		dgFloat32 omegaMag2 = omega.DotProduct(omega).GetScalar() + dgFloat32(1.0e-12f);
		dgFloat32 invOmegaMag = dgRsqrt(omegaMag2);
		dgVector omegaAxis(omega.Scale(invOmegaMag));
		dgFloat32 omegaAngle = invOmegaMag * omegaMag2 * timestep.GetScalar();
		dgQuaternion deltaRotation(omegaAxis, omegaAngle);
		m_gyroRotation = m_gyroRotation * deltaRotation;
		dgAssert((m_gyroRotation.DotProduct(m_gyroRotation) - dgFloat32(1.0f)) < dgFloat32(1.0e-5f));

		matrix = dgMatrix(m_gyroRotation, dgVector::m_wOne);
		localOmega = matrix.UnrotateVector(omega);
		//dgVector angularMomentum(inertia * localOmega);
		//body->m_gyroTorque = matrix.RotateVector(localOmega.CrossProduct(angularMomentum));
		//body->m_gyroAlpha = body->m_invWorldInertiaMatrix.RotateVector(body->m_gyroTorque);
		dgVector localGyroTorque(localOmega.CrossProduct(m_mass * localOmega));
		m_gyroTorque = matrix.RotateVector(localGyroTorque);
		m_gyroAlpha = matrix.RotateVector(localGyroTorque * m_invMass);

		velocStep.m_angular = matrix.RotateVector(gradientStep);
	} else {
		velocStep.m_angular = m_invWorldInertiaMatrix.RotateVector(torque) * timestep;
		//velocStep.m_angular = velocStep.m_angular * dgVector::m_half;
	}

	velocStep.m_linear = force.Scale(m_invMass.m_w) * timestep;
	return velocStep;
}
Пример #2
0
void dgDynamicBody::IntegrateImplicit(dgFloat32 timestep)
{
	// using simple backward Euler or implicit integration, this is. 
	// f'(t + dt) = (f(t + dt) - f(t)) / dt  

	// therefore: 
	// f(t + dt) = f(t) + f'(t + dt) * dt

	// approximate f'(t + dt) by expanding the Taylor of f(w + dt)
	// f(w + dt) = f(w) + f'(w) * dt + f''(w) * dt^2 / 2! + ....

	// assume dt^2 is negligible, therefore we can truncate the expansion to
	// f(w + dt) ~= f(w) + f'(w) * dt

	// calculating dw as the  f'(w) = d(wx, wy, wz) | dt
	// dw/dt = a = (Tl - (wl x (wl * Il)) * Il^1

	// expanding f(w) 
	// f'(wx) = Ix * ax = Tx - (Iz - Iy) * wy * wz 
	// f'(wy) = Iy * ay = Ty - (Ix - Iz) * wz * wx
	// f'(wz) = Iz * az = Tz - (Iy - Ix) * wx * wy
	//
	// calculation the expansion 
	// Ix * ax = (Tx - (Iz - Iy) * wy * wz) - ((Iz - Iy) * wy * az + (Iz - Iy) * ay * wz) * dt
	// Iy * ay = (Ty - (Ix - Iz) * wz * wx) - ((Ix - Iz) * wz * ax + (Ix - Iz) * az * wx) * dt
	// Iz * az = (Tz - (Iy - Ix) * wx * wy) - ((Iy - Ix) * wx * ay + (Iy - Ix) * ax * wy) * dt   
	//
	// factorizing a we get
	// Ix * ax + (Iz - Iy) * dwy * az + (Iz - Iy) * dwz * ay = Tx - (Iz - Iy) * wy * wz
	// Iy * ay + (Ix - Iz) * dwz * ax + (Ix - Iz) * dwx * az = Ty - (Ix - Iz) * wz * wx
	// Iz * az + (Iy - Ix) * dwx * ay + (Iy - Ix) * dwy * ax = Tz - (Iy - Ix) * wx * wy

	dgVector localOmega(m_matrix.UnrotateVector(m_omega));
	dgVector localTorque(m_matrix.UnrotateVector(m_externalTorque - m_gyroTorque));

	// and solving for alpha we get the angular acceleration at t + dt
	// calculate gradient at a full time step
	dgVector gradientStep(localTorque.Scale(timestep));

	// derivative at half time step. (similar to midpoint Euler so that it does not loses too much energy)
	dgVector dw(localOmega.Scale(dgFloat32(0.5f) * timestep));
	//dgVector dw(localOmega.Scale(dgFloat32(1.0f) * timestep));

	// calculates Jacobian matrix (
	//		dWx / dwx, dWx / dwy, dWx / dwz
	//		dWy / dwx, dWy / dwy, dWy / dwz
	//		dWz / dwx, dWz / dwy, dWz / dwz
	//		
	//		dWx / dwx = Ix, dWx / dwy = (Iz - Iy) * wz * dt, dWx / dwz = (Iz - Iy) * wy * dt)
	//		dWy / dwx = (Ix - Iz) * wz * dt, dWy / dwy = Iy, dWy / dwz = (Ix - Iz) * wx * dt
	//		dWz / dwx = (Iy - Ix) * wy * dt, dWz / dwy = (Iy - Ix) * wx * dt, dWz / dwz = Iz
	dgMatrix jacobianMatrix(
		dgVector(m_mass[0], (m_mass[2] - m_mass[1]) * dw[2], (m_mass[2] - m_mass[1]) * dw[1], dgFloat32(0.0f)),
		dgVector((m_mass[0] - m_mass[2]) * dw[2], m_mass[1], (m_mass[0] - m_mass[2]) * dw[0], dgFloat32(0.0f)),
		dgVector((m_mass[1] - m_mass[0]) * dw[1], (m_mass[1] - m_mass[0]) * dw[0], m_mass[2], dgFloat32(0.0f)),
		dgVector::m_wOne);

	gradientStep = jacobianMatrix.SolveByGaussianElimination(gradientStep);

	localOmega += gradientStep;

	m_accel = m_externalForce.Scale(m_invMass.m_w);
	m_alpha = m_matrix.RotateVector(localTorque * m_invMass);

	m_veloc += m_accel.Scale(timestep);
	m_omega = m_matrix.RotateVector(localOmega);
}
size_t SmoothDualDecompositionFistaDescent::run(double rho)
{
    //double rho_end = rho;
    //rho = 10;

    // step length
    double omega;
    omega = _lipschitz_constant_optimistic;
    
    // objectives
    double obj_lambda, obj_y_old;
    obj_y_old = -std::numeric_limits<double>::max();

    // gradient
    Eigen::VectorXd gradient;
    double gnorm = std::numeric_limits<double>::max();
    
    //// TODO: should possibly consider pruning all the labels that have an
    //// inf in theta, but this would get quite messy! Could use the property
    //// if a var is once inf it stays inf in the whole LPQP framework.
    //// TODO: also investigate how much slower the computations get because
    //// of the infs!
    //size_t num_inf = 0;
    //for (size_t v_idx=0; v_idx<_num_vertices; v_idx++) {
    //    for (size_t k=0; k<_num_states[v_idx]; k++) {
    //        if (std::isinf(_theta_unary[v_idx][k])) {
    //            num_inf++;
    //        }
    //    }
    //}
    //std::cout << "num_inf: " << num_inf << std::endl;

    size_t iter = 0;	
    while(!stoppingCriteriaMet(iter, gnorm)){

        //// TODO: play around with this! Seems to work, but we need to improve this!
        //if ((iter % 10) == 0) {
        //    printf("rho before: %f.\n", rho);
        //    rho = adaptRho(_lambda, rho, rho_end, 1e-1);
        //    printf("changed rho: %f.\n", rho);
        //    obj_y_old = computeObjective(rho, _y);
        //}

        _y_old = _y;

        double obj_new;
        obj_new = gradientStep(rho, _lambda, obj_lambda, gradient, gnorm, _u, omega);

        printProgress(iter, obj_new, gnorm, 1.0/omega);
        
        if (obj_new > obj_y_old) {
            _y = _u;
        }
        else {
            _y = _y_old;
        }
        double theta = 2/(static_cast<double>(iter)+2.0);
        _v =  _y_old+1.0/theta*(_u-_y_old);
        theta = 2/(static_cast<double>(iter)+3.0);
        _lambda = (1-theta)*_y+theta*_v;
        obj_y_old = obj_new;
        
        iter++;
	}

    // _y is the final solution 
    _lambda = _y;

    // due to the line search we have to call inference
    // again before returning to actually get the latest marginals of the
    // final value of lambda!
    obj_lambda = computeObjective(rho, _lambda);
    setMarginalsUnary();
    setMarginalsPair();

    return iter;
}