Beispiel #1
0
bool KX_RayCast::RayTest(PHY_IPhysicsEnvironment* physics_environment, const MT_Point3& _frompoint, const MT_Point3& topoint, KX_RayCast& callback)
{
	if(physics_environment==NULL) return false; /* prevents crashing in some cases */
	
	// Loops over all physics objects between frompoint and topoint,
	// calling callback.RayHit for each one.
	//
	// callback.RayHit should return true to stop looking, or false to continue.
	//
	// returns true if an object was found, false if not.
	
	MT_Point3 frompoint(_frompoint);
	const MT_Vector3 todir( (topoint - frompoint).safe_normalized() );
	MT_Point3 prevpoint(_frompoint+todir*(-1.f));
	
	PHY_IPhysicsController* hit_controller;

	while((hit_controller = physics_environment->rayTest(callback,
			frompoint.x(),frompoint.y(),frompoint.z(),
			topoint.x(),topoint.y(),topoint.z())) != NULL) 
	{
		KX_ClientObjectInfo* info = static_cast<KX_ClientObjectInfo*>(hit_controller->getNewClientInfo());
		
		if (!info)
		{
			printf("no info!\n");
			MT_assert(info && "Physics controller with no client object info");
			break;
		}
		
		// The biggest danger to endless loop, prevent this by checking that the
		// hit point always progresses along the ray direction..
		prevpoint -= callback.m_hitPoint;
		if (prevpoint.length2() < MT_EPSILON)
			break;

		if (callback.RayHit(info))
			// caller may decide to stop the loop and still cancel the hit
			return callback.m_hitFound;

		// Skip past the object and keep tracing.
		// Note that retrieving in a single shot multiple hit points would be possible 
		// but it would require some change in Bullet.
		prevpoint = callback.m_hitPoint;
		/* We add 0.001 of fudge, so that if the margin && radius == 0., we don't endless loop. */
		MT_Scalar marg = 0.001 + hit_controller->GetMargin();
		marg *= 2.f;
		/* Calculate the other side of this object */
		MT_Scalar h = MT_abs(todir.dot(callback.m_hitNormal));
		if (h <= 0.01)
			// the normal is almost orthogonal to the ray direction, cannot compute the other side
			break;
		marg /= h; 
		frompoint = callback.m_hitPoint + marg * todir;
		// verify that we are not passed the to point
		if ((topoint - frompoint).dot(todir) < 0.f)
			break;
	}
	return false;
}
bool IK_QJacobianSolver::UpdateAngles(MT_Scalar& norm)
{
	// assing each segment a unique id for the jacobian
	std::vector<IK_QSegment *>::iterator seg;
	IK_QSegment *qseg, *minseg = NULL;
	MT_Scalar minabsdelta = 1e10, absdelta;
	MT_Vector3 delta, mindelta;
	bool locked = false, clamp[3];
	int i, mindof = 0;

	// here we check if any angle limits were violated. angles whose clamped
	// position is the same as it was before, are locked immediate. of the
	// other violation angles the most violating angle is rememberd
	for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
		qseg = *seg;
		if (qseg->UpdateAngle(m_jacobian, delta, clamp)) {
			for (i = 0; i < qseg->NumberOfDoF(); i++) {
				if (clamp[i] && !qseg->Locked(i)) {
					absdelta = MT_abs(delta[i]);

					if (absdelta < MT_EPSILON) {
						qseg->Lock(i, m_jacobian, delta);
						locked = true;
					}
					else if (absdelta < minabsdelta) {
						minabsdelta = absdelta;
						mindelta = delta;
						minseg = qseg;
						mindof = i;
					}
				}
			}
		}
	}

	// lock most violating angle
	if (minseg) {
		minseg->Lock(mindof, m_jacobian, mindelta);
		locked = true;

		if (minabsdelta > norm)
			norm = minabsdelta;
	}

	if (locked == false)
		// no locking done, last inner iteration, apply the angles
		for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
			(*seg)->UnLock();
			(*seg)->UpdateAngleApply();
		}
	
	// signal if another inner iteration is needed
	return locked;
}
Beispiel #3
0
MT_Scalar IK_QJacobian::AngleUpdateNorm() const
{
	int i;
	MT_Scalar mx = 0.0, dtheta_abs;

	for (i = 0; i < m_d_theta.size(); i++) {
		dtheta_abs = MT_abs(m_d_theta[i]);
		if (dtheta_abs > mx)
			mx = dtheta_abs;
	}
	
	return mx;
}
Beispiel #4
0
float KX_LodManager::GetHysteresis(KX_Scene *scene, unsigned short level)
{
	if (!scene->IsActivedLodHysteresis()) {
		return 0.0f;
	}

	KX_LodLevel *lod = m_levels[level];
	KX_LodLevel *lodnext = m_levels[level + 1];

	float hysteresis = 0.0f;
	// if exists, LoD level hysteresis will override scene hysteresis
	if (lodnext->GetFlag() & KX_LodLevel::USE_HYSTERESIS) {
		hysteresis = lodnext->GetHysteresis() / 100.0f;
	}
	else {
		hysteresis = scene->GetLodHysteresisValue() / 100.0f;
	}
	return MT_abs(lodnext->GetDistance() - lod->GetDistance()) * hysteresis;
}
Beispiel #5
0
static MT_Vector3 SphericalRangeParameters(const MT_Matrix3x3& R)
{
	// compute twist parameter
	MT_Scalar tau = ComputeTwist(R);

	// compute swing parameters
	MT_Scalar num = 2.0*(1.0 + R[1][1]);

	// singularity at pi
	if (MT_abs(num) < MT_EPSILON)
		// TODO: this does now rotation of size pi over z axis, but could
		// be any axis, how to deal with this i'm not sure, maybe don't
		// enforce limits at all then
		return MT_Vector3(0.0, tau, 1.0);

	num = 1.0/sqrt(num);
	MT_Scalar ax = -R[2][1]*num;
	MT_Scalar az = R[0][1]*num;

	return MT_Vector3(ax, tau, az);
}
Beispiel #6
0
void IK_QJacobian::InvertSDLS()
{
	// Compute the dampeds least squeares pseudo inverse of J.
	//
	// Since J is usually not invertible (most of the times it's not even
	// square), the psuedo inverse is used. This gives us a least squares
	// solution.
	//
	// This is fine when the J*Jt is of full rank. When J*Jt is near to
	// singular the least squares inverse tries to minimize |J(dtheta) - dX)|
	// and doesn't try to minimize  dTheta. This results in eratic changes in
	// angle. The damped least squares minimizes |dtheta| to try and reduce this
	// erratic behaviour.
	//
	// The selectively damped least squares (SDLS) is used here instead of the
	// DLS. The SDLS damps individual singular values, instead of using a single
	// damping term.

	MT_Scalar max_angle_change = MT_PI/4.0;
	MT_Scalar epsilon = 1e-10;
	int i, j;

	m_d_theta = 0;
	m_min_damp = 1.0;

	for (i = 0; i < m_dof; i++) {
		m_norm[i] = 0.0;
		for (j = 0; j < m_task_size; j+=3) {
			MT_Scalar n = 0.0;
			n += m_jacobian[j][i]*m_jacobian[j][i];
			n += m_jacobian[j+1][i]*m_jacobian[j+1][i];
			n += m_jacobian[j+2][i]*m_jacobian[j+2][i];
			m_norm[i] += sqrt(n);
		}
	}

	for (i = 0; i<m_svd_w.size(); i++) {
		if (m_svd_w[i] <= epsilon)
			continue;

		MT_Scalar wInv = 1.0/m_svd_w[i];
		MT_Scalar alpha = 0.0;
		MT_Scalar N = 0.0;

		// compute alpha and N
		for (j=0; j<m_svd_u.num_rows(); j+=3) {
			alpha += m_svd_u[j][i]*m_beta[j];
			alpha += m_svd_u[j+1][i]*m_beta[j+1];
			alpha += m_svd_u[j+2][i]*m_beta[j+2];

			// note: for 1 end effector, N will always be 1, since U is
			// orthogonal, .. so could be optimized
			MT_Scalar tmp;
			tmp = m_svd_u[j][i]*m_svd_u[j][i];
			tmp += m_svd_u[j+1][i]*m_svd_u[j+1][i];
			tmp += m_svd_u[j+2][i]*m_svd_u[j+2][i];
			N += sqrt(tmp);
		}
		alpha *= wInv;

		// compute M, dTheta and max_dtheta
		MT_Scalar M = 0.0;
		MT_Scalar max_dtheta = 0.0, abs_dtheta;

		for (j = 0; j < m_d_theta.size(); j++) {
			MT_Scalar v = m_svd_v[j][i];
			M += MT_abs(v)*m_norm[j];

			// compute tmporary dTheta's
			m_d_theta_tmp[j] = v*alpha;

			// find largest absolute dTheta
			// multiply with weight to prevent unnecessary damping
			abs_dtheta = MT_abs(m_d_theta_tmp[j])*m_weight_sqrt[j];
			if (abs_dtheta > max_dtheta)
				max_dtheta = abs_dtheta;
		}

		M *= wInv;

		// compute damping term and damp the dTheta's
		MT_Scalar gamma = max_angle_change;
		if (N < M)
			gamma *= N/M;

		MT_Scalar damp = (gamma < max_dtheta)? gamma/max_dtheta: 1.0;

		for (j = 0; j < m_d_theta.size(); j++) {
			// slight hack: we do 0.80*, so that if there is some oscillation,
			// the system can still converge (for joint limits). also, it's
			// better to go a little to slow than to far
			
			MT_Scalar dofdamp = damp/m_weight[j];
			if (dofdamp > 1.0) dofdamp = 1.0;
			
			m_d_theta[j] += 0.80*dofdamp*m_d_theta_tmp[j];
		}

		if (damp < m_min_damp)
			m_min_damp = damp;
	}

	// weight + prevent from doing angle updates with angles > max_angle_change
	MT_Scalar max_angle = 0.0, abs_angle;

	for (j = 0; j<m_dof; j++) {
		m_d_theta[j] *= m_weight[j];

		abs_angle = MT_abs(m_d_theta[j]);

		if (abs_angle > max_angle)
			max_angle = abs_angle;
	}
	
	if (max_angle > max_angle_change) {
		MT_Scalar damp = (max_angle_change)/(max_angle_change + max_angle);

		for (j = 0; j<m_dof; j++)
			m_d_theta[j] *= damp;
	}
}