# Create virtual robtargets and moves inside RAPID program

**URL:** <https://tech-community.robotics.abb.com/t/create-virtual-robtargets-and-moves-inside-rapid-program/6368>\
**Category:** Robot Controller\
**Created:** [November 10, 2014, 1:45pm UTC](https://tech-community.robotics.abb.com/t/create-virtual-robtargets-and-moves-inside-rapid-program/6368 "2014-11-10T13:45:46Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Laro88](https://dub1.discourse-cdn.com/flex005/user_avatar/tech-community.robotics.abb.com/laro88/32/2653_2.png) [@Laro88](https://tech-community.robotics.abb.com/u/Laro88)\
**Post date:** [November 10, 2014, 1:45pm UTC](https://tech-community.robotics.abb.com/t/create-virtual-robtargets-and-moves-inside-rapid-program/6368/1 "2014-11-10T13:45:46Z")

</div>

I have a software issue that I probably need to solve in rapid.  
I need to split one moveL (say 10mm) into a set of moveL instructions separated by say 1mm.  
The reason is that I need to “wiggle” the orient a bit for every 1mm. of motion. To do this I probably meed some some of vector solution so that I can create a subroutine that allows me to programmatically perform this slicing. If I perform this operation on the pc (planning / generation phase) then I end up with some extremely long chains of MoveL - and then it becomes more or less impossible to upload the generated RAPID code.

pseudocode:  
robtargetBegin = robtargetNow //where am I - trivial  
vector3D v3d = robtargetEnd-robtargetBegin  
int steps = v3d.Length / 1mm

for(int ptr=0;ptr\<increment;ptr++)  
robtarget tmp = robtargetBegin+(v3d/steps\*ptr); //calculate target as vectors  
tmp.orient \*= ComputeWiggleOrient(); //multiply the wiggle to the orient to get desired behavior  
MoveL tmp, speedFree, speedFine, toolProgram \WObj:=woWorkTool\_65483223;  
endfor

end pseudo

Is this possible in some clever way?

---

<div class="post-metadata">

**Author:** ![bob865](https://avatars.discourse-cdn.com/v4/letter/b/b2d939/32.png) [@bob865](https://tech-community.robotics.abb.com/u/bob865)\
**Post date:** [November 13, 2014, 9:30am UTC](https://tech-community.robotics.abb.com/t/create-virtual-robtargets-and-moves-inside-rapid-program/6368/2 "2014-11-13T09:30:27Z")

</div>

You can do it with offsets or reltools. You would only have to teach one position(the start) to do it that way. You would need to determine a way to calculate x,y,z offsets along the path. If it’s linear, that’s easy.

---

<div class="post-metadata">

**Author:** ![Laro88](https://dub1.discourse-cdn.com/flex005/user_avatar/tech-community.robotics.abb.com/laro88/32/2653_2.png) [@Laro88](https://tech-community.robotics.abb.com/u/Laro88)\
**Post date:** [November 21, 2014, 6:30am UTC](https://tech-community.robotics.abb.com/t/create-virtual-robtargets-and-moves-inside-rapid-program/6368/3 "2014-11-21T06:30:10Z")

</div>

Here is my code that splits a MoveL into substeps to make the tool wobble while performing a moveL. Not perfect yet, but it actually works nice on ABB140’s

MODULE Wobble  
!Performs a wobbly motion (makes tool pivot rotational) while moving linearly towards the final target

PERS num wobble\_opcount; !global counter to get continuous pivotal behaviour  
PERS string wobblelog;

PROC MoveL\_Wobble(robtarget tgt, speeddata spd, zonedata zone, pers tooldata tool, pers wobjdata wobj)  
VAR robtarget rtNow; !start position  
VAR num dist\_to\_tgt; !distance to final target  
VAR num iStepsNeeded; !how manu steps to split motion into  
VAR num distance\_pr\_increment; !how long is the real stepsize (avoid last step rounding error)

VAR pos unitvector;  
VAR robtarget temptarget;  
VAR robtarget targets{1000};

VAR num angleX;  
VAR num angleY;

wobblelog:=“”;

rtNow := CRobT(\Tool:=tool, \WObj:=wobj);!Determine present location

WobbleWriteLog 101 , “Wobble from:” + WobbleRobtargetToString(rtNow);  
WobbleWriteLog 101 , “Wobble to :” + WobbleRobtargetToString(tgt);

dist\_to\_tgt := Distance(rtNow.trans, tgt.trans);!How far is is the target away  
iStepsNeeded := Round(dist\_to\_tgt / 1); !assume 1mm steps for now  
IF(iStepsNeeded\<1) THEN  
iStepsNeeded := 1;  
ENDIF  
distance\_pr\_increment:=dist\_to\_tgt / iStepsNeeded; !2.5mm / 2teps =\> 1.25mm steps  
WobbleWriteLog 102, “Dist:” + NumToStr(dist\_to\_tgt,2) + “steps:” + NumToStr(iStepsNeeded, 0) + “dist pr step:” + NumToStr(distance\_pr\_increment, 5);  
!compute unit vector to create intermediate targets  
unitvector.x := (tgt.trans.x - rtNow.trans.x) / dist\_to\_tgt;  
unitvector.y := (tgt.trans.y - rtNow.trans.y) / dist\_to\_tgt;  
unitvector.z := (tgt.trans.z - rtNow.trans.z) / dist\_to\_tgt;

!loop to create targets  
FOR i FROM 1 TO iStepsNeeded DO  
!compute target using the initial pos and the unit vector \* step  
targets{i}:=tgt;  
targets{i}.trans.x := rtNow.trans.x + unitvector.x_i;  
targets{i}.trans.y := rtNow.trans.y + unitvector.y_i;  
targets{i}.trans.z := rtNow.trans.z + unitvector.z\*i;

!apply rotational instruction  
angleX := 1 \* Cos(wobble\_opcount_60);  
angleY := 1 \* Sin(wobble\_opcount_60);  
wobble\_opcount := wobble\_opcount + 1;

targets{i}.rot:= targets{i}.rot \* OrientZYX(0,angleY, angleX); !20141117jr yaw pitch correct but does not work  
targets{i}.rot:= targets{i}.rot \* OrientZYX(angleY,angleY, angleX); !20141117jr yaw pitch correct but does not work  
ENDFOR

WobbleWriteLog 103, “wobble opcount:” + NumToStr(wobble\_opcount, 0);

!finally perform the desired motion  
FOR i FROM 1 TO iStepsNeeded DO  
temptarget := targets{i};  
MoveL temptarget, spd, zone, tool \WObj:=wobj;  
WobbleWriteLog 200 + i, “target:” + WobbleRobtargetToString(temptarget);  
ENDFOR

ErrWrite \I, “WobbleLog”, “Debug” \RL2:=wobblelog;  
ENDPROC

PROC WobbleWriteLog(num ID, string Msg)

ErrWrite \I, “ID:” + numtostr(ID, 0), NumToStr(ID,0) + Msg;  
!wobblelog := wobblelog + " " + NumToStr(ID, 0) + “:” + Msg;  
ENDPROC

FUNC string WobbleRobtargetToString(robtarget RT)  
var string position;  
VAR string ori;  
VAR num ax;  
var num ay;  
var num az;  
position := NumToStr(RT.trans.x, 2) + " " + NumToStr(RT.trans.y, 2) + " " + NumToStr(RT.trans.z, 2);

ax := EulerZYX(\X, RT.rot);  
ay := EulerZYX(\Y, RT.rot);  
az := EulerZYX(\Z, RT.rot);

ori := “Angles xyz:” + NumToStr(ax,2) + " " + NumToStr(ay,2) + " " + NumToStr(az,2);  
RETURN position +" "+ori;  
ENDFUNC

ENDMODULE
