PDA

View Full Version : Arm IK



Adam
05-28-2010, 11:33 AM
Hello,

I have arm IK working. However, I have done no formal study on IK, and I'm not sure how my implementation works compared to other approaches. I pretty much just worked out the trigonometry and wrote a software algorithm to do it (I'm a software engineer). I have some questions.

First, when working out the goal positions for a given target point, do you iterate over the entire motion to find the final goal positions up front before moving, or do you physically move in increments and calculate the direction to move at each step? I tried it both ways, and I can only get smooth motion by pre-calculating the final goal positions.

I'll hold off on asking more questions for now. Thanks.

darkback2
05-28-2010, 11:39 AM
Probably your best bet is to post the math that you are using to do what you are doing as well as perhaps some video would help too. Maybe even some sample code?

Quantum
05-28-2010, 12:44 PM
Calculate the end postion first and calculating in incremeants on the fly. Is the way to do it.

I do both and super fluid movements.

Ive finished my IK & FK equations for my Parallax Propeller controller board based of Xan's IK equations. This will be a seperate post with videos/software etc. Dont want to hijack this thread. This weekend I have alot of time.

But the way I have done it is you figure out your end position. The fastest possible movement is from your current servo postion to your end servo postion. But this still will make your movements look jumpy. I created a simple loop that depending on how many steps I want with the start to end loop. Depending on the steps/program loops this value is my interpolation rate.

EX: Servo1 @ 1500 & Servo2 @ 1000 I want to go to Servo1 @ 2000 & Servo2 @ 2000 my loop/interpolation is 10
So Servo1 will move 50 per step and Servo2 will move 100 per step. Both start and finish there movements at the same time. Increasing the interpolation makes the movements smaller and slows down the bot. At 10 steps its flying. In my step program something like 80 to 100 steps is a really nice fluid movement.

But depending on the processor your using your limited. The Propeller has 8 cogs running. 1 Cog runs main program,2 run 32bit floating point math, 1 runs servo controller, 1 runs playstation controller/xbee, 1 running a tilt sesnor, and 2 spares for later add ons.

About 7000 lines of total code.

This is my approach.

Adam
05-28-2010, 01:51 PM
I probably should have mentioned that I'm using Dyanmixels tethered to a PC (for now ). It will eventuall run on a pico-itx, which is still fast enough that processing power is a non-issue for these calculations.


Calculate the end postion first and calculating in incremeants on the fly. Is the way to do it.

I do both and super fluid movements.


Ok, interesting.



But the way I have done it is you figure out your end position. The fastest possible movement is from your current servo postion to your end servo postion. But this still will make your movements look jumpy.


Why does that make it look jumpy?

For me, it's the opposite, moving in increments is jumpy. It's kind of like the tick of a clock. I need to play with some variables and debug a bit deeper to figure out what's going on. The Dynamixel aspect is in play here for me as well.



I created a simple loop that depending on how many steps I want with the start to end loop. Depending on the steps/program loops this value is my interpolation rate.

EX: Servo1 @ 1500 & Servo2 @ 1000 I want to go to Servo1 @ 2000 & Servo2 @ 2000 my loop/interpolation is 10
So Servo1 will move 50 per step and Servo2 will move 100 per step. Both start and finish there movements at the same time. Increasing the interpolation makes the movements smaller and slows down the bot. At 10 steps its flying. In my step program something like 80 to 100 steps is a really nice fluid movement.


It sounds like you are using the interpolation mostly to control the speed. What else does it do for you?



About 7000 lines of total code.


That's a lot of code. :robotsurprised: I assume you mean for the whole bot program. :)

I have a 3DOF arm in two dimensions right now, and the IK part is a couple dozen lines. Adding the third dimension and fourth DOF (base rotate) will add a few more lines of code to that, but I want to really nail the two dimensional stuff first...

I'm trying to find a downside to pre-caculating the goal positions and just moving there. It's smooth with Dynamixels, and I can change speed with one control table variable. I'm probably still missing something. Maybe someone with experience doing IK with Dynamixels can offer some insight.

I'm working on a tweak to the algorithm to decelerate as it gets closer to the target. It's actually pretty easy to do, just make that single speed variable some nice function of the tip to target distance.

Thanks.

darkback2
05-28-2010, 01:59 PM
The issue you are going to run into is the path the end of the arm follows when going from point to point. Try attaching a pen and having it draw a streight line...or a shape. Just knowing the end positions doesn't help with the getting there the way you want. Ofcourse all of this really depends on the end goal. If you are trying to get a hand to pick up and place chess pieces then it may not matter so much.

lnxfergy
05-28-2010, 04:54 PM
You can do it either way. On NUKE powered quads/hexapods, we compute the foot positions at about 5-10hz, but interpolate between them at 30-50hz. The interpolation is nothing fancy, it's done by limiting the angular rates of the servos (this is mainly done to slow down the servos a bit).

On an Arm that I'm currently working on, this wasn't sufficient (for instance, with the base rotation servo, you can't just limit the angular rate, because if the arm is in close vs. out far from the base rotate point, you see two totally different speeds of the end effector, with lizard legs, they tend to stay in the same general region of length from the coxa). My solution here was to interpolate the world coordinate, and compute the IK every time at about 20-30hz. No jumpiness really.

I see two possible issues here that may be causing jumpiness. The first is: how big of a window are you moving the servos. If each little increment is actually pretty big, you get a huge ramp up in speed, move towards the point, ramp down, then the next move comes in, and it ramps up again... This could definitely cause jumpiness. The second thought is: you're using a PC, which is inherently not real-time. Are you sure the jumpiness you're seeing isn't related to the PC not sending the serial data in an even stream (making it more jumpy)?

-Fergs

Adam
05-28-2010, 09:26 PM
Fergs, thanks for the reply. You've given me some good food for thought. I'm going to do some thorough debugging, and I'll respond with more detail and a video when I get a better handle on what's going on.

Adam
05-28-2010, 09:31 PM
The issue you are going to run into is the path the end of the arm follows when going from point to point. Try attaching a pen and having it draw a streight line...or a shape. Just knowing the end positions doesn't help with the getting there the way you want. Ofcourse all of this really depends on the end goal. If you are trying to get a hand to pick up and place chess pieces then it may not matter so much.

Yeah, I understand what you're saying. I'm not quite to the point where I'm thinking much about putting constraints on how I want the joints to move. Aside from getting to the target, I pretty much just want speed control (think Bezier curve). I'm not sure if I really need to use an iterative interpolation algorithm to accomplish that with Dynamixels. I need more testing, will have more to say later.

Adam
05-28-2010, 11:32 PM
Ok, so I did some execution time debugging, and I found out what the problem is.... it's waiting to figure out where to move!

This piece of code in the Forest Moon Dynamixel library is the culprit:



public int CurrentPosition
{
get { return DynNet.ReadRegister(_Id, Register.CurrentPosition); }
}


I should have studied the code more before using it. I was making some assumptions about caching... and there is none. Everytime I get the CurrentPosition, it goes over the Dynamixel network, which takes 15ms, whether the position has changed or not... and I was getting it a bunch of times for each cycle. Anyway, I added some local caching and tightened up my code, and I've got buttery smooth interpolation cycles now. It's a thing of beauty.

Thanks again for the replies.

Adam
05-29-2010, 11:00 PM
Fergs had asked:


how big of a window are you moving the servos.

This is the next question that I wanted to delve into once the jumpiness issue was sorted.

How are folks determining how much to move the servo during each iteration? Right now I'm just using a small fixed value. It works pretty well, but it's not exactly elegant.