Programming a Robot Arm
-
Hi there
I have built a palletizing robot and inserted some servos for the movement. I have programmed them so that you can controll the whole robot with the arrow keys, WASD and space. The endeffector is moving in cartesian coordinates (X, Y, Z, Phi for rotating horizontally) with implemented inverse kinematics and has a gripper to pick up objects. I have put up the current file in the attachment.
But now my problem:
I want to make it somewhat programmable, so that you have commands for PTP, CP, circular interpolation and so on, but to do this in an efficient way I need to know how to make functions/subprograms with transferrable parameters (coordinates for example). Does anyone know, how to do this?
In this way I would get a fully automated and easy programmable robot arm.
Control: W/S: up/down, A/D: rotate, arrow keys: left/right/forward/back, space: close gripper
-
Hi Klaufi,
I like the way you have designed the robot so that the "hand" moves in a straight line and maintains its orientation as the arms rotate. Nicely done!
I am a bit of noob at RUBY but I hope the following helps. I have put a callable procedure in the "OnTick" code box of the "face me" guy and this is called (with parameters) from some code in the "OnTouch" code box of the endeffector. Your original code that was hidden in the physics joint is now in the "OnTick" code box of the solid floor where it is easier to read and debug. See the attached updated file. I have also made it so that the gripper automatically closes when it touches a box and you have to press the spacebar to release the box. I hope you do not mind, I could not resist!
You will need to have the Ruby console open to see the print output of the procedure. It should be enough to get you started. The code in the attached file passes 3 variables to the procedure/function and returns one variable.
To return more than one value from a procedure see http://www.codeodor.com/index.cfm/2007/1/29/Functions-that-return-more-than-one-value/918
I also found these ruby web pages very helpful:
http://www.fincher.org/tips/Languages/Ruby/
http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Method_Calls
Kev
P.S. If you make further refinements to your robot arm, it would be nice to see updates here
-
No problem, I would really like to see how you modified the model, but I have SU6 and since SU7 didn't work on my notebook, SU8 might neither.
The pages look really helpfull, thanks, I will read them when I have more time. -
@unknownuser said:
No problem, I would really like to see how you modified the model, but I have SU6 and since SU7 didn't work on my notebook, SU8 might neither.
The pages look really helpfull, thanks, I will read them when I have more time.Hi Klaufi,
I have saved the modified model as SU6 in the hopes that you might be able to load it, but maybe it is not that simple. Let me know how you get on. See attached.
Kev
-
Oh, the function with grabbing on touch is funny
And I didn't know, that you can put some stuff into the OnTick-field, thats really convenient. But somehow the models I'm downloading lack of hinges and so on. They are there, the simulation runs as it should, but I can't find the objects to manipulate their attributes That's really weird..Edit: I think, now I know, how to make funktions, but now I'm wondering something else: How can I read out the current frame and set some offset onto it, so the function waits the offset till continuing? Or how can I make timed events else?
-
I've played around a bit with functions and came to something like this:
$temp=0; def move(div1) if $frame>=$temp && $frame<div1+$temp; $value=1-($frame-$temp)/div1; #some movement end; if $frame==div1+$temp; $temp=$temp+div1; end; end;
div1 is some divider to set a time, that the joint should move, temp is the temporary variable to set the time to begin the next function, $value is the parameter to transfer to the joint itself. After running the movement in div1 frames, div1 is added to temp, so that the temp'th frame is the new number zero frame for the next function. If I insert something like this:
move(200); move(300);
It should start the second function after finishing the first, but somehow it doesn't even compile. It says:
Undefined method '>=' for nil.NILClass
I don't know, what that means...
-
Note: I have re-uploaded the file to fix a small error on one line of code.
Hi again Klaufi,
Sorry I somehow missed your posts or I would have replied earlier. As I mentioned before I am a bit of Ruby Noob myself, so it helps me to play around with these problems. Here is what I found. First you need to use just "frame" and not "$frame". Secondly, while you can use frame in if equality tests, you can not use its value directly in calculations or even output its value using print or puts. (I don't know why that is and it does not really make sense.). The workaround is to create a function to get the frame number and then pass that frame number as an additional parameter to your "move" function/procedure. Anyway, I managed to get the program to run and reference the frame number in calculations. See the attached file. The code is hidden in the small cylinder and the capsule. The output is to the Ruby Console so you need to open that before running.
Cheers,
Kev.
P.S. Global $variables should be used with caution as they can cause big problems down the line if some other function in SketchyPhysics uses the same global variables. Best to try passing variables between modules as function parameters if you can.
P.P.S. Are you using SP 3.x or SP 3.2?
-
I have Sketchyphysics 3.x and I really should try out SU8, so I can watch your models >_<
But thanks for your effort
Edit: SU8 doesn't work on my notebook, either
Could you please upload it again for SU6? -
-
Thank you, now I have managed to program something useful. This is, what I made so far for testing. Next is to adjust it for the robot.
Thanks for the help this far
-
Hi Klaufi,
I have altered your code a little bit to use arrays for value and the new code illustrates various ways to iterate through, change and print out the the contents of an array. I think you will find the methods useful if your project gets more complex. I have also introduced a "case" construct for the counter, so that that the "move" procedure is not called 5 times every frame, which might speed things up a little. I hope you find the new code informative. Took me while to figure out how to do it, but it is all helping me learn Ruby. I just hope the Ruby etiquette police do not find out we have been using global variables. See the attached SU6 file but just in case that does not work, here is the code:
def getf(frm) frm end f=getf(frame) if f==0 $temp=0 $counter=1;$counter2=0 $value=[0.5,0.5,0.5] $istpos=[0.5,0.5,0.5] end def move(zeit,sollpos,f) if f>=$temp && f<=zeit+$temp; if $counter != $counter2 # Only print to console if counter changes. puts "$counter= #{$counter} zeit= #{zeit} sollpos= #{sollpos.inspect} frame= #{f} " for i in (0..$value.length-1) # one way to iterate through array and print contents. puts "$value[#{i}]= #{$value[i]} " end $counter2 = $counter end $value.each_with_index { |i,j| $value[j]=$istpos[j]+(sollpos[j]-$istpos[j])*(f-$temp)/zeit; } # Another way to iterate through an array. end if f==zeit+$temp+1 $temp=$temp+zeit $counter=$counter+1 $istpos=sollpos puts"$counter=#{$counter} $temp=#{$temp} " puts"$istpos= #{$istpos.inspect} " #quick way to print array contents. end end case $counter when 1 move(150.00,[1,0.3,0.1],f) when 2 move(300.00,[0,0.1,0.2],f) when 3 move(20.00,[1,0.8,1],f) when 4 move(500.00,[1.5,0.9,0.6],f) when 5 move(20.00,[0,0.3,0.2],f) when 6 puts "Programmed sequence ended." $counter+=1 else # do nothing end
Advertisement