47 from robolink
import *
51 PROGRAM_PJX =
'''<?xml version="1.0" encoding="utf-8" ?> 52 <Project xmlns="http://www.staubli.com/robotics/VAL3/Project/3"> 53 <Parameters version="s7.3.1" stackSize="5000" millimeterUnit="true" /> 55 <Program file="start.pgx" /> 56 <Program file="stop.pgx" /> 57 <Program file="setLink.pgx" /> 60 <Data file="%s.dtx" /> 67 PROGRAM_PJX_MAIN =
'''<?xml version="1.0" encoding="utf-8" ?> 68 <Project xmlns="http://www.staubli.com/robotics/VAL3/Project/3"> 69 <Parameters version="s7.3.1" stackSize="5000" millimeterUnit="true" /> 71 <Program file="loadNextOne.pgx" /> 72 <Program file="main.pgx" /> 73 <Program file="start.pgx" /> 74 <Program file="stop.pgx" /> 77 <Data file="%s.dtx" /> 80 <Library alias="prog" path="./%s.pjx" /> 81 <Library alias="prog_swap" path="./%s.pjx" /> 86 START_PGX_MAIN =
'''<?xml version="1.0" encoding="utf-8"?> 87 <Programs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.staubli.com/robotics/VAL3/Program/2"> 88 <Program name="start" access="public"> 91 $XframeLink(frExternal) 99 DATA_DTX =
'''<?xml version="1.0" encoding="utf-8" ?> 100 <Database xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.staubli.com/robotics/VAL3/Data/2"> 102 <Data name="%s" access="public" xsi:type="array" type="frame" size="%i"> 104 <Data name="jPark" access="public" xsi:type="array" type="jointRx" size="1"> 105 <Value key="0" j3="90" j5="90" /> 107 <Data name="%s" access="public" xsi:type="array" type="jointRx" size="%i"> 109 <Data name="mNomSpeed" access="public" xsi:type="array" type="mdesc" size="1"> 110 <Value key="0" blend="off" /> 112 <Data name="%s" access="public" xsi:type="array" type="mdesc" size="%i"> 114 <Data name="nTraj" access="public" xsi:type="array" type="num" size="1"/> 115 <Data name="%s" access="public" xsi:type="array" type="pointRx" size="%i"> 117 <Data name="%s" access="public" xsi:type="array" type="tool" size="%i"> 123 DATA_DTX_MAIN =
'''<?xml version="1.0" encoding="utf-8" ?> 124 <Database xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.staubli.com/robotics/VAL3/Data/2"> 126 <Data name="dioIN" access="public" xsi:type="array" type="dio" size="1"> 127 <Value key="0" link="fIn0" /> 129 <Data name="dioOUT" access="public" xsi:type="array" type="dio" size="1"> 130 <Value key="0" link="fOut0" /> 132 <Data name="dioRotationON" access="public" xsi:type="array" type="dio" size="1"> 133 <Value key="0" link="BasicIO-1\\%%Q0" /> 135 <Data name="dioRotationOFF" access="public" xsi:type="array" type="dio" size="1"> 136 <Value key="0" link="BasicIO-1\\%%Q1" /> 138 <Data name="dioBuse" access="public" xsi:type="array" type="dio" size="1"> 139 <Value key="0" link="BasicIO-1\\%%Q2" /> 141 <Data name="fPartCad" access="public" xsi:type="array" type="frame" size="1"> 143 <Data name="fCadToReal" access="public" xsi:type="array" type="frame" size="1"> 144 <Value key="0" x="0" y="0" z="0" rx="0" ry="0" rz="0" fatherId="fPartCad[0]" /> 146 <Data name="mNomSpeed" access="public" xsi:type="array" type="mdesc" size="1"> 147 <Value key="0" blend="off" /> 149 <Data name="nTraj" access="public" xsi:type="array" type="num" size="1"/> 150 <Data name="nTimeStop" access="private" xsi:type="array" type="num" size="1"/> 151 <Data name="nTimeStart" access="private" xsi:type="array" type="num" size="1"/> 152 <Data name="nMode" access="private" xsi:type="array" type="num" size="1"/> 153 <Data name="nEtat" access="private" xsi:type="array" type="num" size="1"/> 154 <Data name="tCad" access="public" xsi:type="array" type="tool" size="1"> 156 <Data name="frExternal" access="public" xsi:type="array" type="frame" size="1"> 157 <Value key="0" %s fatherId="world[0]" /> 159 <Data name="fWorld0" access="public" xsi:type="array" type="frame" size="1"> 160 <Value key="0" fatherId="world[0]" /> 162 <Data name="tAdjust" access="public" xsi:type="array" type="tool" size="1"> 163 <Value key="0" ioLink="valve1" /> 170 START_PGX =
'''<?xml version="1.0" encoding="utf-8" ?> 171 <Programs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.staubli.com/robotics/VAL3/Program/2"> 172 <Program name="start" access="public"> 183 MAIN_PGX =
'''<?xml version="1.0" encoding="utf-8"?> 184 <Programs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.staubli.com/robotics/VAL3/Program/2"> 185 <Program name="main" access="public"> 186 <Parameters xmlns="http://www.staubli.com/robotics/VAL3/Param/1"> 187 <Parameter name="x_fCellule" type="frame" xsi:type="element" use="reference" /> 190 <Local name="l_nRef0" type="num" xsi:type="array" size="1" /> 191 <Local name="l_nResult" type="num" xsi:type="array" size="1" /> 197 link(fWorld0,x_fCellule) 199 fWorld0.trsf = $Xposition(world,x_fCellule,l_nRef0) 210 STOP_PGX =
'''<?xml version="1.0" encoding="utf-8" ?> 211 <Programs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.staubli.com/robotics/VAL3/Program/2"> 212 <Program name="stop" access="private"> 223 LOAD_NEXT_ONE =
'''<?xml version="1.0" encoding="utf-8" ?> 224 <Programs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.staubli.com/robotics/VAL3/Program/2"> 225 <Program name="loadNextOne" access="private"> 226 <Parameters xmlns="http://www.staubli.com/robotics/VAL3/Param/1"> 227 <Parameter name="x_sName" type="string" xsi:type="element" /> 231 prog_swap:libLoad(x_sName) 238 SETLINK_PGX =
'''<?xml version="1.0" encoding="utf-8"?> 239 <Programs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.staubli.com/robotics/VAL3/Program/2"> 240 <Program name="setLink" access="public"> 241 <Parameters xmlns="http://www.staubli.com/robotics/VAL3/Param/1"> 242 <Parameter name="x_fCellule" type="frame" xsi:type="element" use="reference" /> 246 link(fPartReal,x_fCellule) 255 """Converts a pose to a Staubli target target""" 264 if c > (1.0 - 1e-10):
267 rz1 =
atan2(H[1,0],H[1,1])
268 elif c < (-1.0 + 1e-10):
271 rz1 =
atan2(H[1,0],H[1,1])
282 return [x, y, z, rx1*180.0/pi, ry1*180.0/pi, rz1*180.0/pi]
286 """Prints a pose target""" 288 return (
'x="%.3f" y="%.3f" z="%.3f" rx="%.3f" ry="%.3f" rz="%.3f"' % (x,y,z,r,p,w))
291 """Prints a joint target for Staubli VAL3 XML""" 293 for i
in range(len(angles)):
294 str = str + (
'j%i="%.5f" ' % ((i+1), angles[i]))
300 from tkinter
import filedialog
302 options[
'initialdir'] = strdir
303 options[
'title'] = strtitle
306 file_path = tkinter.filedialog.askdirectory(**options)
312 """Robot post object""" 320 PROG_NAME =
'unknown' 321 MAIN_FOLDER =
'ProgRoboDK' 324 PROG_MOVE_COUNT_MAX = 200
334 SPEED = DEFAULT_SPEED
337 SMOOTH = DEFAULT_SMOOTH
338 REF_NAME =
'fPartReal' 339 REF_CURRENT =
'world[0]' 343 TOOL_CURRENT =
'flange[0]' 348 SPEED_NAME =
'mSpeed' 349 SPEED_CURRENT =
'mNomSpeed' 352 JOINT_NAME =
'jJoint' 355 POINT_NAME =
'pPoint' 359 def __init__(self, robotpost=None, robotname=None, robot_axes = 6, **kwargs):
365 for k,v
in kwargs.items():
366 if k ==
'pose_turntable':
369 elif k ==
'pose_rail':
375 self.
addline(
'// Program %s start' % progname)
380 self.
addline(
'// Program %s end' % progname)
385 """Recursively delete a directory tree on a remote server.""" 388 names = ftp.nlst(path)
389 except ftplib.all_errors
as e:
391 print(
'RemoveDirFTP: Could not remove {0}: {1}'.format(path, e))
395 if os.path.split(name)[1]
in (
'.',
'..'):
continue 396 print(
'RemoveDirFTP: Checking {0}'.format(name))
401 except ftplib.all_errors:
406 except ftplib.all_errors
as e:
407 print(
'RemoveDirFTP: Could not remove {0}: {1}'.format(path, e))
415 robot = RDK.Item(self.
ROBOT_NAME, ITEM_TYPE_ROBOT)
416 [server_ip, port, remote_path, username, password] = robot.ConnectionParams()
418 server_ip =
'localhost' 419 username =
'username' 420 password =
'password' 421 remote_path =
'/usr/usrapp/session/default/saveTraj/CAD' 424 print(
"POPUP: Uploading program through FTP. Enter server parameters...")
428 values_ok =
mbox(
'Using the following FTP connection parameters to transfer the program:\nRobot IP: %s\nRemote path: %s\nFTP username: %s\nFTP password: ****\n\nContinue?' % (server_ip, remote_path, username))
430 print(
"Using default connection parameters")
432 server_ip =
mbox(
'Enter robot IP', entry=server_ip)
434 print(
'FTP upload cancelled by user')
436 remote_path =
mbox(
'Enter the remote path (program folder) on the Staubli robot controller', entry=remote_path)
439 if remote_path.endswith(
'/'):
440 remote_path = remote_path[:-1]
441 rob_user_pass =
mbox(
'Enter user name and password as\nuser-password', entry=(
'%s-%s' % (username, password)))
442 if not rob_user_pass:
444 name_value = rob_user_pass.split(
'-')
445 if len(name_value) < 2:
448 password = name_value[1]
449 username = name_value[0]
450 print(
"POPUP: <p>Connecting to <strong>%s</strong> using user name <strong>%s</strong> and password ****</p><p>Please wait...</p>" % (server_ip, username))
453 if robot
is not None:
454 robot.setConnectionParams(server_ip, port, remote_path, username, password)
457 myFTP = ftplib.FTP(server_ip, username, password)
460 error_str = sys.exc_info()[1]
461 print(
"POPUP: Connection to %s failed: <p>%s</p>" % (server_ip,error_str))
463 contin =
mbox(
"Connection to %s failed. Reason:\n%s\n\nRetry?" % (server_ip,error_str))
467 remote_path_prog = remote_path +
'/' + self.
MAIN_FOLDER 468 myPath =
r'%s' % localpath
469 print(
"POPUP: Connected. Deleting existing files on %s..." % remote_path_prog)
472 print(
"POPUP: Connected. Uploading program to %s..." % server_ip)
475 myFTP.cwd(remote_path)
477 myFTP.cwd(remote_path_prog)
480 error_str = sys.exc_info()[1]
481 print(
"POPUP: Remote path not found or can't be created: %s" % (remote_path))
483 contin =
mbox(
"Remote path\n%s\nnot found or can't create folder.\n\nChange path and permissions and retry." % remote_path)
486 def uploadThis(path):
487 files = os.listdir(path)
490 if os.path.isfile(path +
r'\{}'.format(f)):
491 print(
' Sending file: %s' % f)
492 print(
"POPUP: Sending file: %s" % f)
495 myFTP.storbinary(
'STOR %s' % f, fh)
497 elif os.path.isdir(path +
r'\{}'.format(f)):
498 print(
' Sending folder: %s' % f)
501 uploadThis(path +
r'\{}'.format(f))
506 def ProgSave(self, folder, progname, ask_user = False, show_result = False):
511 if foldersave
is not None and len(foldersave) > 0:
512 foldersave = foldersave
519 print(
"Saving %i programs..." % nprogs)
521 main_progname =
'Main' + progname
523 folderprog = foldersave +
'/' + main_progname
526 folderprog = foldersave +
'/' + progname
531 os.makedirs(folderprog)
536 for i
in range(nprogs):
537 call_sequence+=(
' if prog:libLoad("./%s")!=0\n' % self.
PROG_NAME_LIST[i])
538 call_sequence+=(
' logMsg("Error Loading RoboDK library")\n')
539 call_sequence+=(
' popUpMsg("Error Loading RoboDK library")\n')
540 call_sequence+=(
' endIf\n')
541 call_sequence+=(
' wait(taskStatus("loading")==-1)\n')
543 call_sequence+=(
' taskCreate "loading",10,loadNextOne("./%s")\n' % self.
PROG_NAME_LIST[i+1])
544 call_sequence+=(
' prog:fPartReal.trsf=fPartCad.trsf*fCadToReal.trsf\n')
546 call_sequence+=(
' prog:tCad.trsf=tCad.trsf*tAdjust.trsf\n')
547 call_sequence+=(
' call prog:setLink(fWorld0)\n')
548 call_sequence+=(
' call prog:start()\n')
549 call_sequence+=(
' \n')
553 start_file = folderprog +
'/start.pgx' 554 show_file_list.append(start_file)
555 fid = open(start_file,
"w")
556 fid.write(START_PGX_MAIN)
560 start_file = folderprog +
'/main.pgx' 561 show_file_list.append(start_file)
562 fid = open(start_file,
"w")
563 fid.write(MAIN_PGX % call_sequence)
567 project_file = folderprog +
'/%s.pjx' % main_progname
569 fid = open(project_file,
"w")
571 fid.write(PROGRAM_PJX_MAIN % (main_progname, dummy_folder, dummy_folder))
573 print(
'SAVED: %s\n' % project_file)
576 program_data = folderprog +
'/%s.dtx' % main_progname
577 show_file_list.append(project_file)
578 fid = open(program_data,
"w")
583 stop_file = folderprog +
'/stop.pgx' 584 fid = open(stop_file,
"w")
589 program_data = folderprog +
'/loadNextOne.pgx' 590 fid = open(program_data,
"w")
591 fid.write(LOAD_NEXT_ONE)
595 for i
in range(nprogs):
599 folderprog_final = folderprog
603 os.makedirs(folderprog_final)
607 start_file = folderprog_final +
'/start.pgx' 609 fid = open(start_file,
"w")
614 stop_file = folderprog_final +
'/stop.pgx' 615 fid = open(stop_file,
"w")
620 setlink_file = folderprog_final +
'/setLink.pgx' 621 fid = open(setlink_file,
"w")
622 fid.write(SETLINK_PGX)
626 project_file = folderprog_final +
'/%s.pjx' % self.
PROG_NAME_LIST[i]
628 fid = open(project_file,
"w")
631 print(
'SAVED: %s\n' % project_file)
634 program_data = folderprog_final +
'/%s.dtx' % self.
PROG_NAME_LIST[i]
636 fid = open(program_data,
"w")
645 if type(show_result)
is str:
648 for file_i
in show_file_list:
649 p = subprocess.Popen([show_result, file_i])
652 elif type(show_result)
is list:
654 p = subprocess.Popen(show_result + [filesave])
658 os.startfile(start_file)
659 os.startfile(program_data)
660 if len(self.
LOG) > 0:
661 mbox(
'Program generation LOG:\n\n' + self.
LOG)
665 """Send a program to the robot using the provided parameters. This method is executed right after ProgSave if we selected the option "Send Program to Robot". 666 The connection parameters must be provided in the robot connection menu of RoboDK""" 669 def MoveJ(self, pose, joints, conf_RLF=None):
670 """Add a joint movement""" 675 nextax = len(joints) - 6
680 self.
OTHER_DATA +=
' <Data name="%s" access="private" xsi:type="array" type="num" size="%i">\n' % (var_extax, nextax)
681 for i
in range(nextax):
682 self.
OTHER_DATA +=
' <Value key="%i" value="%.3f" />\n' % (i, joints[i+6])
694 def MoveL(self, pose, joints, conf_RLF=None):
695 """Add a linear movement""" 701 nextax = len(joints) - 6
706 self.
OTHER_DATA +=
' <Data name="%s" access="private" xsi:type="array" type="num" size="%i">\n' % (var_extax, nextax)
707 for i
in range(nextax):
708 self.
OTHER_DATA +=
' <Value key="%i" value="%.3f" />\n' % (i, joints[i+6])
712 str_config =
'shoulder="lefty" elbow="epositive" wrist="wpositive"' 714 [rear, lowerarm, flip] = conf_RLF
715 str_config =
'shoulder="%s" elbow="%s" wrist="%s"' % (
"righty" if rear>0
else "lefty",
"enegative" if lowerarm>0
else "epositive",
"wnegative" if flip>0
else "wpositive")
725 def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None):
726 """Add a circular movement""" 729 if conf_RLF_1 ==
None:
730 str_config =
'shoulder="lefty" elbow="epositive" wrist="wpositive"' 732 [rear, lowerarm, flip] = conf_RLF_1
733 str_config =
'shoulder="%s" elbow="%s" wrist="%s"' % (
"righty" if rear>0
else "lefty",
"enegative" if lowerarm>0
else "epositive",
"wnegative" if flip>0
else "wpositive")
741 def setFrame(self, pose, frame_id=None, frame_name=None):
742 """Change the robot reference frame""" 744 self.
RunMessage(
'Warning: This post processor is meant to use one reference frame. Errors might follow.',
True)
745 self.log(
'This post processor is meant to use one reference frame. Errors might follow.')
754 def setTool(self, pose, tool_id=None, tool_name=None):
755 """Change the robot TCP""" 757 self.
RunMessage(
'Warning: Only one tool allowed per program. Tool change skipped.',
True)
758 self.log(
'Only one tool allowed per program')
769 """Pause the robot program""" 772 self.
addline(
'popUpMsg("Paused. Press OK to continue")')
774 self.
addline(
'delay(%.3f)' % (time_ms*0.001))
777 """Changes the robot speed (in mm/s)""" 787 """Changes the robot acceleration (in mm/s2)""" 791 """Changes the robot joint speed (in deg/s)""" 795 """Changes the robot joint acceleration (in deg/s2)""" 799 """Changes the zone data approach (makes the movement more smooth)""" 804 """Sets a variable (output) to a given value""" 805 if type(io_var) != str:
806 io_var =
'OUT[%s]' % str(io_var)
807 if type(io_value) != str:
814 self.
addline(
'%s=%s' % (io_var, io_value))
816 def waitDI(self, io_var, io_value, timeout_ms=-1):
817 """Waits for an input io_var to attain a given value io_value. Optionally, a timeout can be provided.""" 818 if type(io_var) != str:
819 io_var =
'IN[%s]' % str(io_var)
820 if type(io_value) != str:
828 self.
addline(
'WAIT FOR %s==%s' % (io_var, io_value))
830 self.
addline(
'WAIT FOR %s==%s TIMEOUT=%.1f' % (io_var, io_value, timeout_ms))
832 def RunCode(self, code, is_function_call = False):
833 """Adds code or a function call""" 836 code.replace(
' ',
'_')
837 if not code.endswith(
')'):
841 self.
addline(
'//call prog:%s' % code)
846 """Display a message in the robot controller screen (teach pendant)""" 851 self.
addline(
'popUpMsg("%s")' % message)
855 """Add a program line""" 859 """Add a log message""" 860 self.
LOG = self.
LOG + newline +
'\n' 874 progname = progname + (
'%i' % (nprogs+1))
877 self.
PROG_DTX_LIST.append(DATA_DTX % (self.
REF_NAME, self.
REF_COUNT, self.
REF_DATA, self.
JOINT_NAME, self.
JOINT_COUNT, self.
JOINT_DATA, self.
SPEED_NAME, self.
SPEED_COUNT, self.
SPEED_DATA, self.
POINT_NAME, self.
POINT_COUNT, self.
POINT_DATA, self.
TOOL_NAME, self.
TOOL_COUNT, self.
TOOL_DATA, self.
OTHER_DATA))
908 [x,y,z,r,p,w] = xyzrpw
918 return Mat([[cb*ca, ca*sc*sb - cc*sa, sc*sa + cc*ca*sb, x],[cb*sa, cc*ca + sc*sb*sa, cc*sb*sa - ca*sc, y],[-sb, cb*sc, cc*cb, z],[0,0,0,1]])
921 """Test the post with a basic program""" 925 robot.ProgStart(
"Program")
926 robot.RunMessage(
"Program generated by RoboDK using a custom post processor",
True)
927 robot.setFrame(
Pose([807.766544, -963.699898, 41.478944, 0, 0, 0]))
928 robot.setTool(
Pose([62.5, -108.253175, 100, -60, 90, 0]))
929 robot.MoveJ(
Pose([200, 200, 500, 180, 0, 180]), [-46.18419, -6.77518, -20.54925, 71.38674, 49.58727, -302.54752] )
930 robot.MoveL(
Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
931 robot.MoveL(
Pose([200, 200, 262.132034, 180, 0, -150]), [-43.73892, -3.91728, -35.77935, 58.57566, 54.11615, -253.81122] )
932 robot.RunMessage(
"Setting air valve 1 on")
933 robot.RunCode(
"TCP_On",
True)
935 robot.MoveL(
Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
936 robot.MoveL(
Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
937 robot.MoveL(
Pose([250, 250, 191.421356, 180, 0, -150]), [-39.75778, -1.04537, -40.37883, 52.09118, 54.15317, -246.94403] )
938 robot.RunMessage(
"Setting air valve off")
939 robot.RunCode(
"TCP_Off",
True)
941 robot.MoveL(
Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
942 robot.MoveL(
Pose([250, 200, 278.023897, 180, 0, -150]), [-41.85389, -1.95619, -34.89154, 57.43912, 52.34162, -253.73403] )
943 robot.MoveL(
Pose([250, 150, 191.421356, 180, 0, -150]), [-43.82111, 3.29703, -40.29493, 56.02402, 56.61169, -249.23532] )
944 robot.ProgFinish(
"Program")
946 print(robot.PROG_PGX)
947 if len(robot.LOG) > 0:
948 mbox(
'Program generation LOG:\n\n' + robot.LOG)
950 input(
"Press Enter to close...")
952 if __name__ ==
"__main__":
953 """Function to call when the module is executed by itself: test"""
def addlog(self, newline)
def waitDI(self, io_var, io_value, timeout_ms=-1)
def setSpeed(self, speed_mms)
def RunMessage(self, message, iscomment=False)
def transl(tx, ty=None, tz=None)
def setSpeedJoints(self, speed_degs)
def addline(self, newline)
def setAccelerationJoints(self, accel_degss)
def ProgFinish(self, progname)
def RemoveDirFTP(self, ftp, path)
def MoveJ(self, pose, joints, conf_RLF=None)
def __init__(self, robotpost=None, robotname=None, robot_axes=6, kwargs)
def ProgSendRobot(self, robot_ip, remote_path, ftp_user, ftp_pass)
def setFrame(self, pose, frame_id=None, frame_name=None)
def control_ProgSize(self)
def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None)
def RunCode(self, code, is_function_call=False)
def getSaveFolder(strdir='C:\\', strtitle='Save program folder ...')
def setAcceleration(self, accel_mmss)
def mbox(msg, b1='OK', b2='Cancel', frame=True, t=False, entry=None)
def ProgSave(self, folder, progname, ask_user=False, show_result=False)
def UploadFTP(self, localpath)
def MoveL(self, pose, joints, conf_RLF=None)
def setDO(self, io_var, io_value)
def setTool(self, pose, tool_id=None, tool_name=None)
def setZoneData(self, zone_mm)
def ProgStart(self, progname)