Calling subprogramm from another subprogramm

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

3 Likes

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

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

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

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.

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.

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. 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.

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

image

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:

1 Like

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.