# Calling subprogramm from another subprogramm

**URL:** https://forum.universal-robots.com/t/calling-subprogramm-from-another-subprogramm/218
**Category:** Product Wishlist
**Tags:** welding
**Created:** [September 7, 2016, 1:17pm UTC](https://forum.universal-robots.com/t/calling-subprogramm-from-another-subprogramm/218 "2016-09-07T13:17:51Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![anon42783929](https://avatars.discourse-cdn.com/v4/letter/a/ba8739/32.png) [@anon42783929](https://forum.universal-robots.com/u/anon42783929)
#### Post date: [September 7, 2016, 1:17pm UTC](https://forum.universal-robots.com/t/calling-subprogramm-from-another-subprogramm/218/1 "2016-09-07T13:17:51Z")

</div>

Hi,  
it would great to add possibility of calling subprogramm from another subprogramm without having to use scripts.  
for my application I’ve got multiple subprogramm each corresponding to a production but in each subprogramm I repeat several time the same sequence and for the moment I’m force to copy/paste the sequence each time I need it.

having this functionnality would have allowed me to just make a simple call making the program much easier to read.  
it would also add a lot of programming possibilties in the polyscope interface

---

<div class="post-metadata">

### Author: ![anon15006688](https://avatars.discourse-cdn.com/v4/letter/a/5f9b8f/32.png) [@anon15006688](https://forum.universal-robots.com/u/anon15006688)
#### Post date: [September 7, 2016, 2:26pm UTC](https://forum.universal-robots.com/t/calling-subprogramm-from-another-subprogramm/218/2 "2016-09-07T14:26:49Z")

</div>

One of the things I resorted to doing is creating a Initialize Function script and Initialize Variable script and Just calling everything thing I could as a predefined function instead of Subprogram. Not sure if this is what you are looking for.  
example:  
#-------------------------------------------------------------------------

# ROBOT START POSITION

#-------------------------------------------------------------------------  
def move\_to\_start\_pos():

if (k\>2):  
movej([-1.13443675, -1.480346736, -1.85450897, -1.3510655, 1.503109, -0.36891208], a=1.8, v=3.0)  
end  
if (k==2):  
movej([-1.13237,-1.73678, -2.18847 , - 0.76061 , 1.50325, -0.36844], a=1.8, v=3.0)  
#300mm lower than for k\>2  
end  
if (k\<2):  
movej([-1.13237,-2.17957, -2.25566 , - 0.25063 , 1.50325, -0.36844], a=1.8, v=3.0)  
#550mm lower than for k\>2  
end

end

#-------------------------------------------------------------------------------------------------------------------

# FUNCTION DEFINITION FOR PICK POSITION

#-------------------------------------------------------------------------------------------------------------------

def move\_to\_pick\_pos() :

movel(p[0.10057,-0.63983,PZ-0.001,1.1800,-2.8252,0.1612],a=1.3962634015954636,v=0.50471975511965976)

end

#-------------------------------------------------------------------------------------------------------------------

# FUNCTION DEFINITION FOR RETRACT POSITION

#-------------------------------------------------------------------------------------------------------------------  
def move\_to\_retract\_pos(move\_speed):

#retract position 2 inches up

movel(p[0.10057,-0.63983,PZ+0.034,1.1800,-2.8252,0.1612], a=1.3962634015954636,v=move\_speed)  
return 0  
end  
#-------------------------------------------------------------------------------------------------------------------

# FUNCTION DEFINITION MANIPULATION POSITION

#-------------------------------------------------------------------------------------------------------------------  
def move\_to\_manipulation\_pos():

movel([-1.134436750290873, -1.4803467368137397, -1.8545089714531677, -1.3510655147946053, 1.5031090217924046, -0.36891208762517547], a=1.3962634015954636, v=1.0471975511965976)  
end  
#---------------------------------------------------------------------------------------------------------------------

# FUNCTION VACUUM CUPS ACTIVATION WHEN PICKING 6 CASES

#---------------------------------------------------------------------------------------------------------------------

# TO be deleted later on

def activate\_vacuum\_6():

set\_standard\_digital\_out(1, True)  
set\_standard\_digital\_out(2, True)  
set\_standard\_digital\_out(3, True)  
set\_standard\_digital\_out(4, True)  
set\_standard\_digital\_out(5, True)  
set\_standard\_digital\_out(0, True)  
end

---

<div class="post-metadata">

### Author: ![anon42783929](https://avatars.discourse-cdn.com/v4/letter/a/ba8739/32.png) [@anon42783929](https://forum.universal-robots.com/u/anon42783929)
#### Post date: [September 8, 2016, 1:31pm UTC](https://forum.universal-robots.com/t/calling-subprogramm-from-another-subprogramm/218/3 "2016-09-08T13:31:13Z")

</div>

maybe with an example you’ll have a better vision of what I want to do.  
below is the struccture of the programm I have (its the script generated by polyscope in wich I only left the necessary thing for you to understand). basicaly in my main I can call 2 subprogramm each corresponding to a task. the to task are very similar : I take a screw in a fixed location and I screw it on a part. i do this 3 time in each task.

actual programm :  
def V411\_15062016\_vissage():

def Traj4CycleT9():  
#code to pick a screw  
write\_port\_register(253,9)  
write\_port\_register(252,0)  
write\_port\_register(250,0)  
movej([-2.9521238992230607, -1.292814290267251, 1.9908212812675723, -0.7104551804888581, 1.162431877157648, 0.020028483285286003], a=7.853981633974483, v=2.0943951023931953, r=0.02)  
movej([-2.9520251733431686, -1.2427798716958822, 2.016993971769297, -0.7867436993404411, 1.1624614730974743, 0.02023417547019577], a=7.853981633974483, v=2.0943951023931953)  
write\_port\_register(250,1)  
movel([-2.9519790571130264, -1.1782730282822786, 2.041176717344804, -0.8755353908661654, 1.1624436251818802, 0.020492227300552], a=1.2, v=0.6)  
sleep(0.4)  
movel([-2.9520251733431686, -1.2427798716958822, 2.016993971769297, -0.7867436993404411, 1.1624614730974743, 0.02023417547019577], a=1.2, v=0.6)  
write\_port\_register(252,1)  
movel([-2.948840546689379, -1.2844094640353863, 1.9933263102643721, -0.7213601063809145, 1.1657042364710628, 0.020015619302867833], a=1.2, v=0.6)  
movej([-3.1931641852177712, -1.2582465030249672, 1.9114467716248864, -0.6487440713726791, -0.0316149869218636, 0.024403496840181838], a=7.853981633974483, v=2.0943951023931953, r=0.01)  
movej([-3.4264179477612373, -0.6840110642992485, 1.1596317820044977, -0.4197711643286315, -0.3224758348089516, -0.015732572371568665], a=7.853981633974483, v=2.0943951023931953)  
#end of the ‘pick a screw’ section  
#screwing 1  
movej([-3.2802634921321534, -0.9317892237464918, 1.6489983629403948, -0.6860787335585412, 2.242125980447158, 0.010818009529581118], a=7.853981633974483, v=2.0943951023931953)  
movel([-3.2801755528893954, -0.8620241589456983, 1.6639969269169772, -0.7706593111618218, 2.2421713247055792, 0.011111676566495617], a=1.2, v=0.8)  
sleep(0.1)  
#code to pick a screw  
write\_port\_register(253,9)  
write\_port\_register(252,0)  
write\_port\_register(250,0)  
movej([-2.9521238992230607, -1.292814290267251, 1.9908212812675723, -0.7104551804888581, 1.162431877157648, 0.020028483285286003], a=7.853981633974483, v=2.0943951023931953, r=0.02)  
movej([-2.9520251733431686, -1.2427798716958822, 2.016993971769297, -0.7867436993404411, 1.1624614730974743, 0.02023417547019577], a=7.853981633974483, v=2.0943951023931953)  
write\_port\_register(250,1)  
movel([-2.9519790571130264, -1.1782730282822786, 2.041176717344804, -0.8755353908661654, 1.1624436251818802, 0.020492227300552], a=1.2, v=0.6)  
sleep(0.4)  
movel([-2.9520251733431686, -1.2427798716958822, 2.016993971769297, -0.7867436993404411, 1.1624614730974743, 0.02023417547019577], a=1.2, v=0.6)  
write\_port\_register(252,1)  
movel([-2.948840546689379, -1.2844094640353863, 1.9933263102643721, -0.7213601063809145, 1.1657042364710628, 0.020015619302867833], a=1.2, v=0.6)  
movej([-3.1931641852177712, -1.2582465030249672, 1.9114467716248864, -0.6487440713726791, -0.0316149869218636, 0.024403496840181838], a=7.853981633974483, v=2.0943951023931953, r=0.01)  
movej([-3.4264179477612373, -0.6840110642992485, 1.1596317820044977, -0.4197711643286315, -0.3224758348089516, -0.015732572371568665], a=7.853981633974483, v=2.0943951023931953)  
#end of the ‘pick a screw’ section  
#screwing 2  
write\_port\_register(250,0)  
write\_port\_register(253,17)  
movej([-3.239982493934226, -0.8046736568395891, 1.4043026328938741, -0.5792104342181457, 2.3474051197208663, 0.018987783387459586], a=7.853981633974483, v=1.7453292519943295, r=0.005)  
movel([-3.2423827803166, -0.7546684269553543, 1.4247645630890724, -0.6494878094437144, 2.344958777680449, 0.01921326244165306], a=1.2, v=0.8)  
#code to pick a screw  
write\_port\_register(253,9)  
write\_port\_register(252,0)  
write\_port\_register(250,0)  
movej([-2.9521238992230607, -1.292814290267251, 1.9908212812675723, -0.7104551804888581, 1.162431877157648, 0.020028483285286003], a=7.853981633974483, v=2.0943951023931953, r=0.02)  
movej([-2.9520251733431686, -1.2427798716958822, 2.016993971769297, -0.7867436993404411, 1.1624614730974743, 0.02023417547019577], a=7.853981633974483, v=2.0943951023931953)  
write\_port\_register(250,1)  
movel([-2.9519790571130264, -1.1782730282822786, 2.041176717344804, -0.8755353908661654, 1.1624436251818802, 0.020492227300552], a=1.2, v=0.6)  
sleep(0.4)  
movel([-2.9520251733431686, -1.2427798716958822, 2.016993971769297, -0.7867436993404411, 1.1624614730974743, 0.02023417547019577], a=1.2, v=0.6)  
write\_port\_register(252,1)  
movel([-2.948840546689379, -1.2844094640353863, 1.9933263102643721, -0.7213601063809145, 1.1657042364710628, 0.020015619302867833], a=1.2, v=0.6)  
movej([-3.1931641852177712, -1.2582465030249672, 1.9114467716248864, -0.6487440713726791, -0.0316149869218636, 0.024403496840181838], a=7.853981633974483, v=2.0943951023931953, r=0.01)  
movej([-3.4264179477612373, -0.6840110642992485, 1.1596317820044977, -0.4197711643286315, -0.3224758348089516, -0.015732572371568665], a=7.853981633974483, v=2.0943951023931953)  
#end of the ‘pick a screw’ section   
#screwing 3  
write\_port\_register(253,19)  
movej([-3.2675743356874007, -0.8083154591221273, 1.4112182848032024, -0.5830337885745678, 2.3198126500374796, 0.018215456541135665], a=7.853981633974483, v=2.0943951023931953, r=0.02)  
movel([-3.267512455287351, -0.7593649390138753, 1.424712412917711, -0.6453350765614356, 2.319841651519912, 0.018425638666511], a=1.2, v=0.8)  
end

def Traj5CycleK0\_P8():  
#same structure as "Traj4CycleT9()"  
end

$ 2 "AvantDémarrage"  
write\_port\_register(241,0)  
write\_port\_register(254,1)  
sleep(0.2)  
write\_port\_register(241,0)  
while (True):  
write\_port\_register(254,0)  
movej([-3.1931641852177717, -1.2582465030249663, 1.9114467716248862, -0.6487440713726782, -0.0316149869218636, 0.024403496840181994], a=7.853981633974483, v=2.0943951023931953)  
global program\_number=read\_port\_register(138)  
$ 41 "Si program\_number≟4"  
if (program\_number == 4):  
Traj4CycleT9()  
movej([-3.1931641852177717, -1.2582465030249663, 1.9114467716248862, -0.6487440713726782, -0.0316149869218636, 0.024403496840181994], a=7.853981633974483, v=2.0943951023931953)  
write\_port\_register(252,1)  
end  
$ 47 "Si program\_number≟5"  
if (program\_number == 5):  
Traj5CycleK0\_P8()  
movej([-3.1931641852177717, -1.2582465030249663, 1.9114467716248862, -0.6487440713726782, -0.0316149869218636, 0.024403496840181994], a=7.853981633974483, v=2.0943951023931953)  
end  
end  
end

---

<div class="post-metadata">

### Author: ![anon42783929](https://avatars.discourse-cdn.com/v4/letter/a/ba8739/32.png) [@anon42783929](https://forum.universal-robots.com/u/anon42783929)
#### Post date: [September 8, 2016, 1:36pm UTC](https://forum.universal-robots.com/t/calling-subprogramm-from-another-subprogramm/218/4 "2016-09-08T13:36:29Z")

</div>

here is what I would like to have :  
def Traj4CycleT9():  
pick\_a\_screw()  
#screwing 1  
movej([-3.2802634921321534, -0.9317892237464918, 1.6489983629403948, -0.6860787335585412, 2.242125980447158, 0.010818009529581118], a=7.853981633974483, v=2.0943951023931953)  
movel([-3.2801755528893954, -0.8620241589456983, 1.6639969269169772, -0.7706593111618218, 2.2421713247055792, 0.011111676566495617], a=1.2, v=0.8)  
sleep(0.1)  
pick\_a\_screw()  
#screwing 2  
write\_port\_register(250,0)  
write\_port\_register(253,17)  
movej([-3.239982493934226, -0.8046736568395891, 1.4043026328938741, -0.5792104342181457, 2.3474051197208663, 0.018987783387459586], a=7.853981633974483, v=1.7453292519943295, r=0.005)  
movel([-3.2423827803166, -0.7546684269553543, 1.4247645630890724, -0.6494878094437144, 2.344958777680449, 0.01921326244165306], a=1.2, v=0.8)  
pick\_a\_screw()  
#screwing 3  
write\_port\_register(253,19)  
movej([-3.2675743356874007, -0.8083154591221273, 1.4112182848032024, -0.5830337885745678, 2.3198126500374796, 0.018215456541135665], a=7.853981633974483, v=2.0943951023931953, r=0.02)  
movel([-3.267512455287351, -0.7593649390138753, 1.424712412917711, -0.6453350765614356, 2.319841651519912, 0.018425638666511], a=1.2, v=0.8)  
end

def pick\_a\_screw():  
#code to pick a screw  
write\_port\_register(253,9)  
write\_port\_register(252,0)  
write\_port\_register(250,0)  
movej([-2.9521238992230607, -1.292814290267251, 1.9908212812675723, -0.7104551804888581, 1.162431877157648, 0.020028483285286003], a=7.853981633974483, v=2.0943951023931953, r=0.02)  
movej([-2.9520251733431686, -1.2427798716958822, 2.016993971769297, -0.7867436993404411, 1.1624614730974743, 0.02023417547019577], a=7.853981633974483, v=2.0943951023931953)  
write\_port\_register(250,1)  
movel([-2.9519790571130264, -1.1782730282822786, 2.041176717344804, -0.8755353908661654, 1.1624436251818802, 0.020492227300552], a=1.2, v=0.6)  
sleep(0.4)  
movel([-2.9520251733431686, -1.2427798716958822, 2.016993971769297, -0.7867436993404411, 1.1624614730974743, 0.02023417547019577], a=1.2, v=0.6)  
write\_port\_register(252,1)  
movel([-2.948840546689379, -1.2844094640353863, 1.9933263102643721, -0.7213601063809145, 1.1657042364710628, 0.020015619302867833], a=1.2, v=0.6)  
movej([-3.1931641852177712, -1.2582465030249672, 1.9114467716248864, -0.6487440713726791, -0.0316149869218636, 0.024403496840181838], a=7.853981633974483, v=2.0943951023931953, r=0.01)  
movej([-3.4264179477612373, -0.6840110642992485, 1.1596317820044977, -0.4197711643286315, -0.3224758348089516, -0.015732572371568665], a=7.853981633974483, v=2.0943951023931953)  
#end of the ‘pick a screw’ section   
end

and i would like to do it without using scripts

---

<div class="post-metadata">

### Author: ![mbush](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.universal-robots.com/mbush/32/76_2.png) [@mbush](https://forum.universal-robots.com/u/mbush)
#### Post date: [September 24, 2016, 2:53am UTC](https://forum.universal-robots.com/t/calling-subprogramm-from-another-subprogramm/218/5 "2016-09-24T02:53:33Z")

</div>

Why not break up the Traj4CycleT9() subprogram into a picking screw subprogram and then a move subprogram? You could keep track of the screw position that you are in with an installation variable and then your main call would be something like:

```
if (program_number == 4):
  screw_number_installation_var := 0
  while (screw_number_installation_var <3)
    pick_screw_subprogram()
    place_screw_subprogram() #This would use the installation variable
    screw_number_installation_var = screw_number_installation_var + 1
  end
end

```

Or something along these lines. I agree it would be great if you could call subprograms from within subprograms but it does not exist at least for today.

---

<div class="post-metadata">

### Author: ![anon32310726](https://avatars.discourse-cdn.com/v4/letter/a/8baadc/32.png) [@anon32310726](https://forum.universal-robots.com/u/anon32310726)
#### Post date: [May 27, 2021, 6:36am UTC](https://forum.universal-robots.com/t/calling-subprogramm-from-another-subprogramm/218/6 "2021-05-27T06:36:22Z")

</div>

I still would like to have this function for state programing. Now I use folders and script to “call” a second degree subprogram.

**What do i want?**  
what I would like to see is a X degree subprogram function. A 2nd degree subprogram can be called in 1st degree subprogram and the mainprogram, but the 2nd program can’t be called in a 3th program or an other 2nd degree program.

**why is it needed?**  
Now i call my 2nd degree subprograming “start welding” inside a folder. it contains some safty presets and it calls the welding machine. Now i sometimes change this preset and i want to change tis to all my program and to the other programs. would help a lot.

---

<div class="post-metadata">

### Author: ![rasmus.larsson](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.universal-robots.com/rasmus.larsson/32/3158_2.png) [@rasmus.larsson](https://forum.universal-robots.com/u/rasmus.larsson)
#### Post date: [January 10, 2022, 5:31pm UTC](https://forum.universal-robots.com/t/calling-subprogramm-from-another-subprogramm/218/7 "2022-01-10T17:31:26Z")

</div>

I would second this, also for other reasons.

I’m making a quite large program, where I’m not the only developer, so even if I’m used with making script programs, some of my colleagues are not. I would also like to use this to show new colleagues in the future how to make complex programs simpler.

So to keep it quite simple, I need to have an overview with nodes in the GUI instead of writing loads of smaller script programs, where I would for example like to set TCP, manipulate and verify grippers in loads of different places. I first tried to separate it into very small subprograms, then I wanted to refactor bigger operation into a subprogram, but as of now, that means I can’t do it like that, as that bigger operation needs to also use those smaller subprograms.

My first work around idea was ofc to make the smaller simpler things into a script, well named, like the setting of the TCP. But then I need to hardcode the TCP values in the script, [as I don’t seem to be able to get the TCP and payload as variables from anywhere](https://forum.universal-robots.com/t/set-tcp-by-refering-name-from-polyscope-measured-tcps-list/9525). And for the gripper, it means I need to copy paste the script code from a URCap programnode (Which is not always neat.).

In the end, a complete mess, though better…

So right now I don’t see any other way than to broader subprograms for the major things (pick, manipulate, place etc) and just copy paste nodes for TCP setting, gripper manipulating and verification etc in multiple subprograms.

These small things would be sooooo much easier if I could just be allowed to run a subprogram in another subprogram. I don’t see the reason why it’s not allowed.

I did some quick calculations, my program which is now around 400 nodes in GUI could easily be under 300 if I could just use subprograms in subprograms.

---

<div class="post-metadata">

### Author: ![eric.feldmann](https://avatars.discourse-cdn.com/v4/letter/e/94ad74/32.png) [@eric.feldmann](https://forum.universal-robots.com/u/eric.feldmann)
#### Post date: [January 10, 2022, 6:30pm UTC](https://forum.universal-robots.com/t/calling-subprogramm-from-another-subprogramm/218/8 "2022-01-10T18:30:49Z")

</div>

I’ll leave this here, because it is essentially exactly what this request is for:

![image](https://us1.discourse-cdn.com/flex020/uploads/universal_robots/original/2X/6/6d9d494e30c8207c6a298ecc8a6ba6b07d42b5e8.png)

You can simply insert a subprogram without a Call instruction, and execute the subprogram via a script line with the name of the subprogram and (). Using this method, you can call subprograms from other subprograms no problem. See this other reply for another example:

> [@Jump Flag Program Node](https://forum.universal-robots.com/t/jump-flag-program-node/17355/2):
>
> While not an explicit Polyscope Node, you can already achieve this functionality using a combination of Switch/Case and subprogram calls (or script function calls). Let your main program consist entirely of one large switch/case, and let sensors (possibly put in threads) set the switching variable. Each case can contain a single line, a Call Subprogram instruction. The only downside to this method is that subprograms cannot be called from within subprograms. (Not cleanly through Polyscope, anywa…

---

<div class="post-metadata">

### Author: ![rasmus.larsson](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.universal-robots.com/rasmus.larsson/32/3158_2.png) [@rasmus.larsson](https://forum.universal-robots.com/u/rasmus.larsson)
#### Post date: [January 11, 2022, 7:23am UTC](https://forum.universal-robots.com/t/calling-subprogramm-from-another-subprogramm/218/9 "2022-01-11T07:23:04Z")

</div>

Oh, that’s good, ofc I didn’t think about that.

But at the same time, that makes it even more unclear for me why it’s blocked to call subprograms as nodes in other subprograms…  
My argument, about ease of understandability and consistency, still stands in that sense, but it’s good that there is an easy to understand workaround for it.
