# Can somone help me with my IK?

This topic is 4909 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I followed this website to add IK to my setup. At first all I got was a jittery mess and it looked like the robot was fighting it self but verrrrry slowly aproaching the target. I fiddled with it and now it does absolutely nothing. Well it does something because if I add a break to the 'torque=' line while its running I find that value is in the area of 0.0001345 Here is my related code: jn are my bone locations nn are my bone axis' p is the target a Vector along the axis of the joint. b Vector along the bone. r Vector at Right angles to a and b. f Force vector, from End Point to Target. I hacked most of the math from the real soon now milkshape demo.
float dot(Vector a, Vector b)
{
float vals1[3], vals2[3];

memcpy(vals1, a.getVector(), sizeof(float)*3);
memcpy(vals2, b.getVector(), sizeof(float)*3);

return  (vals1[0]*vals2[0] + vals1[1]*vals2[1] + vals1[2]*vals2[2]);
}

Vector cross(Vector a, Vector b)
{
float val[3];
float vals1[3];
float vals2[3];
Vector v;

memcpy(vals1, a.getVector(), sizeof(float)*3);
memcpy(vals2, b.getVector(), sizeof(float)*3);

val[0] = vals1[1] * vals2[2] - vals1[2] * vals2[1]; // Ay*Bz - Az*By;
val[1] = vals1[2] * vals2[0] - vals1[0] * vals2[2]; //Az*Bx - Ax*Bz;
val[2] = vals1[0] * vals2[1] - vals1[1] * vals2[0]; // Ax*By - Ay*Bx;

v.set(val);

return v;
}

void Model::IK(float *p, int iter, bool draw)
{
Vector a,b,r,f;

float vals[3], z[] = {0,0,0};
float torque[7];
float fmag;

memset(torque, 0, sizeof(float)*7);

for (int i = m_numJoints - 2; i > -1; i--)
//int i = 4;

{
if (i != 3 && i != 0)
{
a.set(nn.getVector());
a.sub(jn.getVector());
//a.normalize();

b.set(jn[i+1].getVector());
b.sub(jn.getVector());
//b.normalize();

r = cross(a, b);
//r.neg();
//r.normalize();

f.set(p);
f.sub(jn[5].getVector());

fmag = f.length();
//f.normalize();

if (draw)
{
glBegin(GL_LINES);
glColor3f(0,1,0);
glVertex3fv(a.getVector());
glVertex3fv(z);

glColor3f(0,0,1);
glVertex3fv(b.getVector());
glVertex3fv(z);

glColor3f(1,0,0);
glVertex3fv(r.getVector());
glVertex3fv(z);

glColor3f(1,1,0);
glVertex3fv(f.getVector());
glVertex3fv(z);
glEnd();
}

//torque = Mag(f) * SinVect(a, f) * SinVect(b, f) * sign(CosVect(r, f)) * Sensitivity
torque = fmag * sin(dot(a, f)) * sin(dot(b, f)) * sin(cos(dot(r, f))) * .01 ;
}
}

//if (!draw)
{
for (int i = 0 ; i < m_numJoints; i++)
{
joints[i*3+2] -= torque;
}
}
}


Some questions: Should I be normalizing those vectors? When I did the first time the model would explode, after some fiddleing thats when it decided not to work at all. What is a normal value for 'Sensitivity'? I would say that my vector calculations are pritty acurate. When I draw them on the screen they point in all the correct directions, I can see when the torque should be positive or negative, but its always around the same very low value.

##### Share on other sites
//torque = Mag(f) * SinVect(a, f) * SinVect(b, f) * sign(CosVect(r, f)) * Sensitivity
torque = fmag * sin(dot(a, f)) * sin(dot(b, f)) * sin(cos(dot(r, f))) * .01 ;

--

These look odd to me... Is the second line supposed to do the same as the first? If so, then this might be a problem. The 4th term in the first expression uses "sign" whereas you have used "sin".

Just a thought.

-Josh

##### Share on other sites
Thank you, I beleive that helped but did not fix my problem.

Here are two exe's one for each of the following code
clicky

With Subtract

void Model::IK(float *p, int iter, bool draw){	Vector a,b,r,f;	float vals[3], z[] = {0,0,0};	double torque[7];	float fmag;	double s1,s2,s3;	f.set(p);	f.sub(jn[5].getVector());	fmag = f.length();	memset(torque, 0, sizeof(double)*7);	for (int i = m_numJoints - 2; i > -1; i--)	{		if (i != 3 && i != 0)		{			a.set(nn.getVector());			a.sub(jn.getVector()); //<-- this line makes a big difference			//a.normalize();			b.set(jn[i+1].getVector());			b.sub(jn.getVector());			//b.normalize();			r = cross(a, b);			//r.neg();			//r.normalize();			//torque = Mag(f) * SinVect(a, f) * SinVect(b, f) * sign(CosVect(r, f)) * Sensitivity			s1 = sin(dot(a, f));			s2 = sin(dot(b, f));			s3 = sign(cos(dot(r, f)));			 torque = fmag * s1 * s2 * s3 * .001 ;			if (draw) 			{				glBegin(GL_LINES);				glColor3f(0,1,0);				a.mult(10);				a.add(jn.getVector());				glVertex3fv(a.getVector());				glVertex3fv(jn.getVector());				glColor3f(0,0,1);				b.mult(10);				b.add(jn.getVector());				glVertex3fv(b.getVector());				glVertex3fv(jn.getVector());				glColor3f(1,0,0);				r.mult(10);				r.add(jn.getVector());				glVertex3fv(r.getVector());				glVertex3fv(jn.getVector());				glEnd();			}		}	}	if (draw)	{		glBegin(GL_LINES);		glColor3f(1,1,0);		f.add(jn[5].getVector());		glVertex3fv(f.getVector());		glVertex3fv(jn[5].getVector());		glEnd();	}	//if (!draw)	{		joints[14] += torque[4];		joints[8] += torque[2];		joints[5] += torque[1];		advanceAnimation(joints);	}}

void Model::IK(float *p, int iter, bool draw){	Vector a,b,r,f;	float vals[3], z[] = {0,0,0};	double torque[7];	float fmag;	double s1,s2,s3;	f.set(p);	f.sub(jn[5].getVector());	fmag = f.length();	memset(torque, 0, sizeof(double)*7);	for (int i = m_numJoints - 2; i > -1; i--)	{		if (i != 3 && i != 0)		{			a.set(nn.getVector());			//a.sub(jn.getVector()); //<- now ik does nothing			//a.normalize();			b.set(jn[i+1].getVector());			b.sub(jn.getVector());			//b.normalize();			r = cross(a, b);			//r.neg();			//r.normalize();			//torque = Mag(f) * SinVect(a, f) * SinVect(b, f) * sign(CosVect(r, f)) * Sensitivity			s1 = sin(dot(a, f));			s2 = sin(dot(b, f));			s3 = sign(cos(dot(r, f)));			 torque = fmag * s1 * s2 * s3 * .001 ;			if (draw) 			{				glBegin(GL_LINES);				glColor3f(0,1,0);				a.mult(10);				a.add(jn.getVector());				glVertex3fv(a.getVector());				glVertex3fv(jn.getVector());				glColor3f(0,0,1);				b.mult(10);				b.add(jn.getVector());				glVertex3fv(b.getVector());				glVertex3fv(jn.getVector());				glColor3f(1,0,0);				r.mult(10);				r.add(jn.getVector());				glVertex3fv(r.getVector());				glVertex3fv(jn.getVector());				glEnd();			}		}	}	if (draw)	{		glBegin(GL_LINES);		glColor3f(1,1,0);		f.add(jn[5].getVector());		glVertex3fv(f.getVector());		glVertex3fv(jn[5].getVector());		glEnd();	}	//if (!draw)	{		joints[14] += torque[4];		joints[8] += torque[2];		joints[5] += torque[1];		advanceAnimation(joints);	}}

It dosnt make sense that I have to subtract the "base point" from the vector because the vector is not in the bone space, it is centered at the origin (0,0,0). You'll notice the vectors look much better if I dont subtract it, but the IK does nothing then.

Vectors:

Blue is in the direction of the bone.
Green is in the direction of the axis rotation.
Red is the cross product.
yellow is the "force" on the end affector.

Vectors are displayed x10 for visiblity. In normal.exe they are normalized before calculations.

[Edited by - honayboyz on August 15, 2005 7:12:03 PM]

##### Share on other sites
Well, you want to take the cross product of the vectors a and b with respect to the origin. The origin in this case is defined to be jn, which I guess is the reference point of the ith bone. The vector, r, is the resulting cross product and it will be perpendicular to both a and b.

What does f.length() return? Is it the number of dimensions of the vector? If that's the case, I think you should use Mag(f) from the original code.

Also, I suspect that you should normalize those vectors to get stable results.

The call to r.neg() is not necessary. If you use r = cross(b,a) it will be equivalent to r = cross(a,b); r.neg(); No point in doing extra work :)

-Josh

##### Share on other sites

Got it working, It's completely differnt, just trig no interations. It's not finished or perfect yet but it's functional and really simple.

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 14
• 12
• 15
• 11
• 12
• ### Forum Statistics

• Total Topics
634153
• Total Posts
3015846
×