Jump to content
  • Advertisement
Sign in to follow this  
bzroom

Can somone help me with my IK?

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

If you intended to correct an error in the post then please contact us.

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;
		}
		advanceAnimation(joints);
	}
}




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 this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster
//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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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.

Download.




Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!