Quazi's Tuts: Part 1: The 2 Armed IK Solver

Post your own tutorials, guides and demos.

Post » Sat Jan 02, 2010 5:57 pm



This is part 1 in a planned series of tutorials. like the title suggests, this tutorial will be explaining how to build your very own 2 armed IK solver, and although plugins exist to do so, this is a stepping stone towards creating advanced expressions in construct, and what will be learned here is going to be used in my next tutorial explaining how to build a 3 armed IK solver, something which doesn't have a plugin to do all the work for you. i'll also point out some advantages of doing this on your own vs a plugin towards the end.

For those of you who dont know, an IK (inverse kinematic) solver, is something which can make an articulated group of objects touch a point which you specify. its ultra handy for making dynamic character animation, (make your character hold a gun properly, or move his arm towards your cursor etc.) and it'll add life to your character you just cant get any other way. for example

DOWNLOAD REALTIME EXAMPLE

the robot seen here and at the beginning of this tut is completely rigged up using IK, i can move his arms and legs where ever i want, as can you (its drag and droppable!), and they'll go there and do exactly as i tell them. now if that isn't control over your animation, i dunno what is.

[quote:2cxgz3fd]the only file youll need to download for this tutorial is this small (15.5 kb zip file) containing the two .caps youll be needing.

[color=#BF0000:2cxgz3fd][size=200:2cxgz3fd]DOWNLOAD[/size:2cxgz3fd][/color:2cxgz3fd][/quote:2cxgz3fd]

so without further ado, heres the tutorial! (feel free to skim if your more advanced, this is meant to be descriptive)

[size=200:2cxgz3fd]Part 1: 2 Armed IK solver[/size:2cxgz3fd]

When I set up an ik solve in my caps, I always use the method im about to show you. I import the same graphics that have been provided here, and give them the SAME names. The name part is important, because if you want to be able to reuse long expressions, objects need to have the same names in order to be picked and behave as they have in other caps. Once you copy and paste the expression, you can rename the object in the layout editor, and everything will still work, since the names in the events will all change



As you can see here, we have a root object, which is simply the root, or beginning point of the ik, and we use it storing all the linkages variables later on, but for now just remember its the point the arms are attached to, a shoulder. Then we have an A object, this is simply the first arm, and a B object, this is the second arm, they share the same graphic, with the same hotspot, and the same image point at the point of the arm, so that we can find the end of the arms. And place other things to that point without having to deal with any trigonometry.Then, we have another important object, the End object, this is a point that the arms will try to touch, and if they cannot, theyll get the closest possible that they can. Its the control point of the linkage.



One important thing to note, is that these 4 objects are in a container. If you dont already know what these are, I dont suggest you be doing this tutorial right now, but deadeyes platform school, or ghost shooter instead. But even so, I will give a brief description, because I doubt anyone's going to take my advice :P.

A container simply means that all the objects are in a group, and one cannot exist on its own, so when you create one, you create a all the objects in said container. An even more important feature of containers, is that it relates objects within the same container for object picking differently than it would, an object that isn't a part of it. What's different is that if you were to lets say, tell "A" to set position to "ROOT", in an always event, which wouldnt specify which "A" to attach out of a whole bunch, it would only pick the "A" in the same container group of the "ROOT". So if we picked a certain "root" in some other condition, and set "A" to it, without specifying anything about "A", it would know which "A" to pick and it would only pick said "A" for that "ROOT", and none other, even though the event didnt specify otherwise. I'm going to ask you to all open up the provided cap called "2 arm ik"

Add each object to a container now , if you did everything right it should look like the image below, and add a drag and drop behavior to "END", and "ROOT", this is just to simplify testing.



So now we have everything we need so far set up layout wise. Time to move onto the daunting part, EVENTS. Yea this might be a little scary to some people, what do I do IZ so hard!?, or some other peoples reaction, I cant do anything with this, its for b3ginn3rs and I r is too 1337 for it, I know GML your both wrong, this is what makes construct so awesome! but anyways, open up the event editor right now.

Were gonna start the IK solver events, add a For each from the system object, and make it a for each Root, it should look like this. For eachs run the event for each object of that type, picking that object when they run for it, and consequently will pick the related objects in the container, if you ever specify an action for those.



Add an action that sets a new private variable your about to create for "ROOT" called C to this

[code:2cxgz3fd]clamp(distance(Root.x,Root.y,End.x,End.y),abs(A.width-B.width)+0.0000000001,A.width+B.width) [/code:2cxgz3fd]



which ill explain later, and now make another variable called AC and set it to

[code:2cxgz3fd]Angle(Root.x,Root.y,End.x,End.y)[/code:2cxgz3fd]



Now if these two events look complicated to you, I suggest reading over the SYSTEM EXPRESSIONS article on the construct wiki.
http://sourceforge.net/apps/mediawiki/c ... xpressions
try looking for all the things I used, and understanding what purpose they served.Now that we have all the actual values we need to solve the ik, we can do just that!The method I used was that of the intersection of two circles
http://local.wasp.uwa.edu.au/~pbourke/geometry/2circle/
http://mathworld.wolfram.com/Circle-Cir ... ction.html
and another way to look at it is the law of cosines for solving an unknown angle in a triangle who's sides we all know.
http://mathworld.wolfram.com/LawofCosines.html
if youre pretty good with math, I suggest you try figuring out the rest of what you need to do on your own, as it will be a great exercise, and then look for possible problems with your method. Remember that I figured out how to do this on my own, using only these references a long time ago and sparked the creation of a plug-in by some else to make it even easier. If you can figure out how to convert the above references into a working construct example like I did, I salute you, and I'm sure youll make a fine constructor indeed young padwan.For those of you who are too lazy to try, or dont believe you can figure it out, dont worry. I'm going to give you the nice cut and pastable expression, and for those of you who did, please read over this part as there are a number of things you might not of realised while trying to build your own expression, limiting the ability of what you can do with your solver.



First off, you wanna be sure to set "A"s position to "ROOT" (remember the container we made a while ago) try to think how that would make multiple pairs of "A"s and "ROOTS"s react because of this action in the for each. now make an extra "ROOT" in the layout, run the layout, and see what happens? Were you correct in your assumptions? If you were you should of seen two "ROOTS"s with two "A"s sticking out of them. But you didnt create two "A"s? it doesnt matter, everything in the container must exist as long as one of the elements does, destroying one of the elements will destroy them all. There was also an extra "B" and an extra "END", but you didnt see them because
they were stacked coincidently (in the same position, angle etc.) as the other ones. Anywho, now that "A" is tethered to the "ROOT", we can set its angle in the direction it needs to be for the arms to reach the end point (or the closest point to it). Remember what we are trying to achieve here. IK stands for inverse kinematics, a fancy way of saying, we want to determine the orientation of a bunch of connected arms, so that the arm linkage's very tip, reaches a point that we give it. So right now we are orienting "A" in an angle that would allow it to be exactly an arm "B"s length away from the endpoint (or the closest real solution near it without breaking the arm,
more about how this is done in our expressions later)



So, remember how I said were using the circle intersection solving method?, what I just said should make you able to understand why we used it. If not ill explain. Imagine the center of the red circle as ROOT, and the center of the blue one as End. The radiuses of said circles are arms A and B in their respective order (red and blue= A and B). If you take a moment to look at how circles intersect, we realise its the points where both radiuses can touch each others ends. This can be though of the joint, we also notice that the combination of the distance between the two center points, and the raiduses, make up the sides of a triangle, this explains why we used the distance formula, and why were going to use the law of cosines. Also note how we have two completely opposite triangles formed, since there are two intersections, but more on this later.For now, remember that what were about to do, is find the angle for a A (or the red radius) where it touches the outside (or radius distance from the center point) of the blue circle. If you dont get this its ok, itll make sense as we near the end of the process, just remember the radius lengths represent arm lengths, and think about that while looking at the above photo.

OK so without further delay, heres what we need to do. Set the angle of A, to

[code:2cxgz3fd]Root('AC')+acos((A.Width^2+Root('C')^2-B.Width^2)/(2*A.width*Root('C')))*Root('dir')[/code:2cxgz3fd]

your going to need to define a variable dir for the object root once you press finish. Thats why the textbox turned yellow. Remember to set the initial value for dir to 1 or -1 nothing else. You wont be do anything important by making it anything else than those, but Ill explain later as to why.

Hmm that looks awfully complicated doesnt it? Well if you read about the law of cosines it should look really familiar, besides one or two things near the beginning and end. Also remember that ^ means raise to power, so DOG^2, would mean the value DOG to the power of 2, or DOGxDOG. Note how we use the width of the arms as side lengths. And root(C) as one as well. Root(C), is the distance between END and ROOT, and we called it C because its our third arm in the triangle! A.width, B.width, and root(C)? get it!? Anyways, this was the last big expression, in fact the last one for this part of the tut. Now all we have to do is position B onto the end of A, by adding an action set Bs position to A and then in the text box below, write point with the quotations finally, create an event which sets Bs angle towards END. We could have made another expression like the one above, but that would have just been a waste of time since it would have gave us the exact same result.

If you did everything correctly things should look like this:



If not I provided a cap called 2 arm finished with the completed example. Look at it and see where you went wrong.

So now everything's completed, and you can start playing around with what you made, go to the layout editor and make a bunch of roots. Then run the layout. You should see a whole bunch of arms pointing toward one end, this is simply because you didnt create any extra ends, and so construct spawned all of them on the same point (coincident and containers again). Drag and drop the end/s to split them apart. To stop this from happening just make extra ends and it'll show you which ones are for which roots. Also try adjusting the widths of certain arms to make asymmetrical ones.



Now remember the variable you created for the roots called dir? You might be wondering what its for, and its really important. Do you also remember how there were 2 intersections between the circles? Each with a triangle exactly opposite the other one formed by them?. Well, you see, the variable dir in each root allows us to control the orientation of the arm attached to it, by setting dir to either 1, or -1. go ahead try it (you can set variables in the layout editor, look in the properties bar)



Do you also remember way back when we set root(C), how the distance formula had a bunch of other stuff next to it

[code:2cxgz3fd]clamp(distance(Root.x,Root.y,End.x,End.y),abs(A.width-B.width)+0.0000000001,A.width+B.width)[/code:2cxgz3fd]

Well, if we break up this equation we see that the Clamp(param,param,param) encompasses everything, I suggest you actually go read the systen expressions page in the wiki if you already havent, and look at what clamp does. If you know what it does, youll see that the value being clamped is the distance.



why do we need to clamp it? Well if you look at the left most image here, you'll realize, that it has no solutions! If we were to evaluate the expression without clamping distance, it would very well be possible to end up with this result, but instead we clamp it so that it returns a value similar to the middle picture when its too great.

This value is simply the sum of both radiuses, or alternatively, the sum of both our arm lengths. On the other end of the clamping spectrum, what It does isn't very apparent. Thats because the arm lengths are equal. If you stretch the width of one of them longer, youll notice that the arm cant find a real solution if the end comes in too close. Imagine one circle being inside the other, and their edges dont touch. Well the other end of the clamp makes the arm behave like your seeing, instead of freaking out all over the place do to a lack of solutions, it finds the closes possible one, a distance which is the absolute value (+ version only of a number) of the difference between arm lengths. As a picture it would look like a circle with its edge up against the other, while still remaining completely inside of the bigger one. The addition of 0.000000001 that you see is simply to prevent the value from being zero, as that would cause a distributive property of zero problem or wtv you'd call it, and would return an infinite number of solutions since the circles would be coincident.

If you'd still like to learn more about what I did, simply tinker with my expressions, deleting or altering things you dont understand, and seeing how the ik solver behaves without those things. I also recommend you read the tuts I pointed out before hand.

Linkman's IK solver plug-in can do almost everything you just learned, but I dont use because im kind of stubborn in my ways, and it doesnt seem to account for the circle inside circle problem (if and when you read this linkman! Fix that bug if you already haven't :P) also you have control over things you dont in the plug-in if you understand the expression, you can alter the clamping zones, you can artificially extend arms, ect. and anyways, I hope you learned something :P and the principles covered here will need to be used when I show you how to make my 3 armed, isosceles trapezoid method solver, which doesnt currently have a plug-in (but probably will soon enough ;P)



[size=200:2cxgz3fd]well thats all for this part of the tutorial folks![/size:2cxgz3fd]

if you notice any errors or somethings werent clear just point them out in the comments section, and ill explain or fix them!
B
52
S
7
G
6
Posts: 1,945
Reputation: 7,610

Post » Sun Jan 03, 2010 3:21 pm

Wow! This is fantastic!
I'll be doing this tutorial soon!

Great stuff as usual, Quazi!
B
107
S
40
G
10
Posts: 456
Reputation: 13,202

Post » Thu Jan 07, 2010 2:48 am

Kick. Ass. Great tutorial 9.8/10. The point two is because I am a grammar Nazi and it hurt my eyes to see "were" used as "we are". I am not trying to be a dick, it really bothers me, however... your mad math skillz were quite impressive and made the pain in my retinas quickly dissipate. I loved the tutorial and hope to see more! This is fantastic.
B
2
G
3
Posts: 46
Reputation: 942

Post » Thu Jan 07, 2010 3:25 am

[quote="QuaziGNRLnose":3lz1kylg]Linkman's IK solver plug-in can do almost everything you just learned, but I dont use because im kind of stubborn in my ways, and it doesnt seem to account for the circle inside circle problem (if and when you read this linkman! Fix that bug if you already haven't :P)[/quote:3lz1kylg]
I'm fairly certain I fixed that back in November, when Newt brought it up -- unless the problem you're talking about is different from the one I am. :P However, maybe I should go back and make a true new version of the plugin.

Cool tutorial, by the way. Very in-depth and informative.
Moderator
B
98
S
37
G
19
Posts: 1,584
Reputation: 17,817

Post » Fri Jan 08, 2010 1:46 am

A few questions I have.
1. I am trying to set this up with legs, similar to your robot. How did you get the feet to keep the guy in the air?
2. How would you animate these limbs, like you have. I am setting the positions of the "end" objects to image points on a sprite. Are there better ways to do this?
B
2
G
3
Posts: 46
Reputation: 942

Post » Fri Jan 08, 2010 2:15 am

[quote="Fresh Frijoles":1sxfqi9j]A few questions I have.
1. I am trying to set this up with legs, similar to your robot. How did you get the feet to keep the guy in the air?
2. How would you animate these limbs, like you have. I am setting the positions of the "end" objects to image points on a sprite. Are there better ways to do this?[/quote:1sxfqi9j]

the feet don't keep him up in the air, his waist is animated separately from them with a sine oscillation, and it simply looks like they are :P

theres literally, A TON of ways to animate them. if what your doing works theres nothing wrong with it, but in my cap it uses alterable bezier paths, which are kind of complicated to set up if you don't know how. for a walking animation, wtv looks good and suits your needs is fine.

the robot also has a special routine to stick feet above the ground, which adds to the walking effect.
i cant really say if theres a "better" way to animate them, my method is cumbersome and confusing in all honesty, and unless you want an adaptable walking pattern theres really no reason for it.

i think the best way for you to do what you want might be adding the ends as bones to some big character object, and simply move them using bone movement and bone movement animations. all the tweening stuff and animation controls are set up for you already.

i cant really say anymore, its all up to your imagination! the purpose of the tutorial is to show you how to make IK arms using my method, and i don't wanna show everyone how i do the animating itself in one single "model", because then a lot of stuff will just end up being a clone of it. i give you tools, you have to build the car/tank/airplane/giant spider robot with your own imagination :P

anyways, i really think that bone movement ends method would be the easiest/best looking for what your trying to do.
B
52
S
7
G
6
Posts: 1,945
Reputation: 7,610

Post » Fri Jan 08, 2010 3:49 am

Thanks for the reply, in that case I suppose I will keep with the image-point method. One thing I would like to know, if you are willing to divulge the info. You may not want to, and I wouldn't blame you...
I went to the wine engine website and saw the IK engine you were using for your engine. How are you managing to keep the feet from... uhh... how do you make them follow terrain? Can you? Did I misinterpret. I'm sure it is possible, but how would you go about it. I'm sure the math involved would be insane.
[quote:2gv594w6]the feet don't keep him up in the air[/quote:2gv594w6]
And I figured out that when I tried making the feet on my character solid, and then tried adding Platform behavior to them. :P doesn't work.
B
2
G
3
Posts: 46
Reputation: 942

Post » Fri Jan 08, 2010 4:34 am

[quote="Fresh Frijoles":2ykkkyoh]I went to the wine engine website and saw the IK engine you were using for your engine. How are you managing to keep the feet from... uhh... how do you make them follow terrain?[/quote:2ykkkyoh]

well, thats not really as math related as it is programming logic. its actually not that complicated, and dont worry its no secret, platform movements use the same kinda tech to keep a character from falling through the ground :P

all it does is simply check for intersection, and if there is one, using a loop, moves the "end" up 1 pixel, then checks again, repeats until there is no intersection. and when there isnt an intersection, it moves the end down, checks and repeats, until its at the "surface". its a simple loop based system, but remember loops can be cpu heavy if you make them too long or use too many, or if they do complex things.

now detecting surface points is easy, but making the walk algorithm over these surfaces is a diff story, and im soon going to go back to the whine engine and get that working properly, the canvas bugs are finally fixed so work can recommence work on the project! procedural walking animation, will surely be awesome when its up and running.
B
52
S
7
G
6
Posts: 1,945
Reputation: 7,610

Post » Fri Jan 08, 2010 4:48 am

Thanks for the info breh, I think I understand what you are saying, I may have to rescan that block of text a few times to let it sink in. And by the way... who did the sexy pixel art on that robot? If I may say it is very, very nice.

Edit:
I take that back, for some reason my image point method wont work with walking. It works fine for reloading, jumping and crouching. For some odd reason however It refuses to work with the walking animations.
B
2
G
3
Posts: 46
Reputation: 942

Post » Fri Jan 08, 2010 4:53 am

[quote="Fresh Frijoles":275mmjgm]Thanks for the info breh, I think I understand what you are saying, I may have to rescan that block of text a few times to let it sink in. And by the way... who did the sexy pixel art on that robot? If I may say it is very, very nice.[/quote:275mmjgm]

that was me, i always make everything from scratch, i feel like i cheaped out otherwise :P
and thank you for the compliments on everything, they're much appreciated.

i have so little time and so many things i want to finish, i really aught to finish the game with that robot in it.
B
52
S
7
G
6
Posts: 1,945
Reputation: 7,610

Next

Return to Your tutorials & example files

Who is online

Users browsing this forum: No registered users and 2 guests