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" />    59     <Data file="%s.dtx" />    66 PROGRAM_PJX_MAIN = 
'''<?xml version="1.0" encoding="utf-8" ?>    67 <Project xmlns="http://www.staubli.com/robotics/VAL3/Project/3">    68   <Parameters version="s7.3.1" stackSize="5000" millimeterUnit="true" />    70     <Program file="loadNextOne.pgx" />    71     <Program file="start.pgx" />    72     <Program file="stop.pgx" />    75     <Data file="%s.dtx" />    78     <Library alias="prog" path="./%s.pjx" />    79     <Library alias="prog_swap" path="./%s.pjx" />    80     <Library alias="tooldata" path="saveChangeTool" />    84 DATA_DTX = 
'''<?xml version="1.0" encoding="utf-8" ?>    85 <Database xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.staubli.com/robotics/VAL3/Data/2">    87     <Data name="%s" access="public" xsi:type="array" type="frame" size="%i">    89     <Data name="jPark" access="public" xsi:type="array" type="jointRx" size="1">    90       <Value key="0" j1="0.000" j2="0.000" j3="90.000" j4="0.000" j5="90.000" j6="0.000" />    92     <Data name="%s" access="public" xsi:type="array" type="jointRx" size="%i">    94     <Data name="mNomSpeed" access="public" xsi:type="array" type="mdesc" size="1">    95       <Value key="0" accel="100" vel="100" decel="100" tmax="99999" rmax="99999" blend="off" leave="50" reach="50" />    97     <Data name="%s" access="public" xsi:type="array" type="mdesc" size="%i">    99     <Data name="nTraj" access="public" xsi:type="array" type="num" size="1"/>   100     <Data name="nTimeStop" access="private" xsi:type="array" type="num" size="1"/>   101     <Data name="nTimeStart" access="private" xsi:type="array" type="num" size="1"/>   102     <Data name="nMode" access="private" xsi:type="array" type="num" size="1"/>   103     <Data name="nEtat" access="private" xsi:type="array" type="num" size="1"/>   104     <Data name="%s" access="public" xsi:type="array" type="pointRx" size="%i">   106     <Data name="%s" access="public" xsi:type="array" type="tool" size="%i">   112 DATA_DTX_MAIN = 
'''<?xml version="1.0" encoding="utf-8" ?>   113 <Database xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.staubli.com/robotics/VAL3/Data/2">   115     <Data name="dioIN" access="public" xsi:type="array" type="dio" size="1">   116       <Value key="0" link="fIn0" />   118     <Data name="dioOUT" access="public" xsi:type="array" type="dio" size="1">   119       <Value key="0" link="fOut0" />   121     <Data name="dioRotationON" access="public" xsi:type="array" type="dio" size="1">   122       <Value key="0" link="BasicIO-1\\%%Q0" />   124     <Data name="dioRotationOFF" access="public" xsi:type="array" type="dio" size="1">   125       <Value key="0" link="BasicIO-1\\%%Q1" />   127     <Data name="dioBuse" access="public" xsi:type="array" type="dio" size="1">   128       <Value key="0" link="BasicIO-1\\%%Q2" />   130     <Data name="fPartCad" access="public" xsi:type="array" type="frame" size="1">   132     <Data name="fCadToReal" access="public" xsi:type="array" type="frame" size="1">   133       <Value key="0" x="0" y="0" z="0" rx="0" ry="0" rz="0" fatherId="fPartCad[0]" />   135     <Data name="mNomSpeed" access="public" xsi:type="array" type="mdesc" size="1">   136       <Value key="0" accel="100" vel="100" decel="100" tmax="99999" rmax="99999" blend="off" leave="50" reach="50" />   138     <Data name="nTraj" access="public" xsi:type="array" type="num" size="1"/>   139     <Data name="nTimeStop" access="private" xsi:type="array" type="num" size="1"/>   140     <Data name="nTimeStart" access="private" xsi:type="array" type="num" size="1"/>   141     <Data name="nMode" access="private" xsi:type="array" type="num" size="1"/>   142     <Data name="nEtat" access="private" xsi:type="array" type="num" size="1"/>   143     <Data name="tCad" access="public" xsi:type="array" type="tool" size="1">   150 START_PGX = 
'''<?xml version="1.0" encoding="utf-8" ?>   151 <Programs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.staubli.com/robotics/VAL3/Program/2">   152   <Program name="start" access="public">   163 STOP_PGX = 
'''<?xml version="1.0" encoding="utf-8" ?>   164 <Programs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.staubli.com/robotics/VAL3/Program/2">   165   <Program name="stop" access="private">   176 LOAD_NEXT_ONE = 
'''<?xml version="1.0" encoding="utf-8" ?>   177 <Programs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.staubli.com/robotics/VAL3/Program/2">   178   <Program name="loadNextOne" access="private">   179     <Parameters xmlns="http://www.staubli.com/robotics/VAL3/Param/1">   180       <Parameter name="x_sName" type="string" xsi:type="element" />   184   prog_swap:libLoad(x_sName)   192     """Converts a pose to a Staubli target target"""   201     if c > (1.0 - 1e-10):
   204         rz1 = 
atan2(H[1,0],H[1,1])
   205     elif c < (-1.0 + 1e-10):
   208         rz1 = 
atan2(H[1,0],H[1,1])
   219     return [x, y, z, rx1*180.0/pi, ry1*180.0/pi, rz1*180.0/pi]
   223     """Prints a pose target"""   225     return (
'x="%.3f" y="%.3f" z="%.3f" rx="%.3f" ry="%.3f" rz="%.3f"' % (x,y,z,r,p,w))
   228     """Prints a joint target for Staubli VAL3 XML"""   230     for i 
in range(len(angles)):
   231         str = str + (
'j%i="%.5f" ' % ((i+1), angles[i]))
   237     from tkinter 
import filedialog
   239     options[
'initialdir'] = strdir
   240     options[
'title'] = strtitle
   243     file_path = tkinter.filedialog.askdirectory(**options)
   249     """Robot post object"""       254     PROG_NAME = 
'unknown'   255     MAIN_FOLDER = 
'ProgRoboDK'   258     PROG_MOVE_COUNT_MAX = 200
   268     SPEED = DEFAULT_SPEED
   271     SMOOTH = DEFAULT_SMOOTH
   272     REF_NAME = 
'fPartReal'   273     REF_CURRENT = 
'world[0]'   277     TOOL_CURRENT = 
'flange[0]'   280     SPEED_NAME = 
'mSpeed'   281     SPEED_CURRENT = 
'mNomSpeed'   284     JOINT_NAME = 
'jJoint'   287     POINT_NAME = 
'pPoint'   291     def __init__(self, robotpost=None, robotname=None, robot_axes = 6, **kwargs):
   300         self.
addline(
'// Program %s start' % progname)
   305         self.
addline(
'// Program %s end' % progname)
   310         """Recursively delete a directory tree on a remote server."""   313             names = ftp.nlst(path)
   314         except ftplib.all_errors 
as e:
   316             print(
'RemoveDirFTP: Could not remove {0}: {1}'.format(path, e))
   320             if os.path.split(name)[1] 
in (
'.', 
'..'): 
continue   321             print(
'RemoveDirFTP: Checking {0}'.format(name))
   326             except ftplib.all_errors:
   331         except ftplib.all_errors 
as e:
   332             print(
'RemoveDirFTP: Could not remove {0}: {1}'.format(path, e))
   340             robot = RDK.Item(self.
ROBOT_NAME, ITEM_TYPE_ROBOT)
   341             [server_ip, port, remote_path, username, password] = robot.ConnectionParams()
   343             server_ip = 
'localhost'     344             username = 
'username'        345             password = 
'password'        346             remote_path = 
'/usr/usrapp/session/default/saveTraj/CAD'    349             print(
"POPUP: Uploading program through FTP. Enter server parameters...")
   353             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))
   355                 print(
"Using default connection parameters")
   357                 server_ip = 
mbox(
'Enter robot IP', entry=server_ip)
   359                     print(
'FTP upload cancelled by user')
   361                 remote_path = 
mbox(
'Enter the remote path (program folder) on the Staubli robot controller', entry=remote_path)
   364                 if remote_path.endswith(
'/'):
   365                     remote_path = remote_path[:-1]
   366                 rob_user_pass = 
mbox(
'Enter user name and password as\nuser-password', entry=(
'%s-%s' % (username, password)))
   367                 if not rob_user_pass:
   369                 name_value = rob_user_pass.split(
'-')
   370                 if len(name_value) < 2:
   373                     password = name_value[1]
   374                 username = name_value[0]
   375             print(
"POPUP: <p>Connecting to <strong>%s</strong> using user name <strong>%s</strong> and password ****</p><p>Please wait...</p>" % (server_ip, username))
   378             if robot 
is not None:
   379                 robot.setConnectionParams(server_ip, port, remote_path, username, password)
   382                 myFTP = ftplib.FTP(server_ip, username, password)
   385                 error_str = sys.exc_info()[1]
   386                 print(
"POPUP: Connection to %s failed: <p>%s</p>" % (server_ip,error_str))
   388                 contin = 
mbox(
"Connection to %s failed. Reason:\n%s\n\nRetry?" % (server_ip,error_str))
   392         remote_path_prog = remote_path + 
'/' + self.
MAIN_FOLDER   393         myPath = 
r'%s' % localpath
   394         print(
"POPUP: Connected. Deleting existing files on %s..." % remote_path_prog)
   397         print(
"POPUP: Connected. Uploading program to %s..." % server_ip)
   400             myFTP.cwd(remote_path)
   402             myFTP.cwd(remote_path_prog)
   405             error_str = sys.exc_info()[1]
   406             print(
"POPUP: Remote path not found or can't be created: %s" % (remote_path))
   408             contin = 
mbox(
"Remote path\n%s\nnot found or can't create folder.\n\nChange path and permissions and retry." % remote_path)
   411         def uploadThis(path):
   412             files = os.listdir(path)
   415                 if os.path.isfile(path + 
r'\{}'.format(f)):
   416                     print(
'  Sending file: %s' % f)
   417                     print(
"POPUP: Sending file: %s" % f)
   420                     myFTP.storbinary(
'STOR %s' % f, fh)
   422                 elif os.path.isdir(path + 
r'\{}'.format(f)):
   423                     print(
'  Sending folder: %s' % f)
   426                     uploadThis(path + 
r'\{}'.format(f))
   431     def ProgSave(self, folder, progname, ask_user = False, show_result = False):
   436             if foldersave 
is not None and len(foldersave) > 0:
   437                 foldersave = foldersave
   444         print(
"Saving %i programs..." % nprogs)
   446         main_progname = 
'Main' + progname
   448             folderprog = foldersave + 
'/' + main_progname
   451             folderprog = foldersave + 
'/' + progname
   456             os.makedirs(folderprog)
   461             for i 
in range(nprogs):
   462                 call_sequence+=(
'  if prog:libLoad("./%s")!=0\n' % self.
PROG_NAME_LIST[i])
   463                 call_sequence+=(
'    logMsg("Error Loading RoboDK library")\n')
   464                 call_sequence+=(
'    popUpMsg("Error Loading RoboDK library")\n')
   465                 call_sequence+=(
'  endIf\n')
   466                 call_sequence+=(
'  wait(taskStatus("loading")==-1)\n')
   468                     call_sequence+=(
'  taskCreate "loading",10,loadNextOne("./%s")\n' % self.
PROG_NAME_LIST[i+1])                    
   469                 call_sequence+=(
'  prog:fPartReal.trsf=fPartCad.trsf*fCadToReal.trsf\n')
   470                 call_sequence+=(
'  prog:tCad.trsf=prog:tCad.trsf*{0,0,tooldata:nLength,0,0,0}\n')               
   471                 call_sequence+=(
'  call prog:start()\n')
   472                 call_sequence+=(
'  \n')
   476             start_file = folderprog + 
'/start.pgx'   477             show_file_list.append(start_file)
   478             fid = open(start_file, 
"w")
   479             fid.write(START_PGX % call_sequence)
   483             project_file = folderprog + 
'/%s.pjx' % main_progname
   485             fid = open(project_file, 
"w")
   487             fid.write(PROGRAM_PJX_MAIN % (main_progname, dummy_folder, dummy_folder))
   489             print(
'SAVED: %s\n' % project_file)
   492             program_data = folderprog + 
'/%s.dtx' % main_progname
   493             show_file_list.append(project_file)
   494             fid = open(program_data, 
"w")
   499             stop_file = folderprog + 
'/stop.pgx'   500             fid = open(stop_file, 
"w")
   505             program_data = folderprog + 
'/loadNextOne.pgx'   506             fid = open(program_data, 
"w")
   507             fid.write(LOAD_NEXT_ONE)
   511         for i 
in range(nprogs):
   515                 folderprog_final = folderprog
   519                 os.makedirs(folderprog_final)
   523             start_file = folderprog_final + 
'/start.pgx'   525             fid = open(start_file, 
"w")
   530             stop_file = folderprog_final + 
'/stop.pgx'   531             fid = open(stop_file, 
"w")
   536             project_file = folderprog_final + 
'/%s.pjx' % self.
PROG_NAME_LIST[i]
   538             fid = open(project_file, 
"w")
   541             print(
'SAVED: %s\n' % project_file)
   544             program_data = folderprog_final + 
'/%s.dtx' % self.
PROG_NAME_LIST[i]
   546             fid = open(program_data, 
"w")
   555             if type(show_result) 
is str:
   558                 for file_i 
in show_file_list:
   559                     p = subprocess.Popen([show_result, file_i])
   562             elif type(show_result) 
is list:
   564                 p = subprocess.Popen(show_result + [filesave])   
   568                 os.startfile(start_file)
   569                 os.startfile(program_data)
   570             if len(self.
LOG) > 0:
   571                 mbox(
'Program generation LOG:\n\n' + self.
LOG)
   575         """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".   576         The connection parameters must be provided in the robot connection menu of RoboDK"""   579     def MoveJ(self, pose, joints, conf_RLF=None):
   580         """Add a joint movement"""   591     def MoveL(self, pose, joints, conf_RLF=None):
   592         """Add a linear movement"""   599             str_config = 
'shoulder="lefty" elbow="epositive" wrist="wpositive"'   601             [rear, lowerarm, flip] = conf_RLF
   602             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")
   608     def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None):
   609         """Add a circular movement"""   612         if conf_RLF_1 == 
None:
   613             str_config = 
'shoulder="lefty" elbow="epositive" wrist="wpositive"'   615             [rear, lowerarm, flip] = conf_RLF_1
   616             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")
   624     def setFrame(self, pose, frame_id=None, frame_name=None):
   625         """Change the robot reference frame"""   627             self.
RunMessage(
'Warning: This post processor is meant to use one reference frame. Errors might follow.', 
True)
   628             self.log(
'This post processor is meant to use one reference frame. Errors might follow.')
   637     def setTool(self, pose, tool_id=None, tool_name=None):
   638         """Change the robot TCP"""   640             self.
RunMessage(
'Warning: Only one tool allowed per program. Tool change skipped.', 
True)
   641             self.log(
'Only one tool allowed per program')
   652         """Pause the robot program"""   655             self.
addline(
'popUpMsg("Paused. Press OK to continue")')
   657             self.
addline(
'delay(%.3f)' % (time_ms*0.001))
   660         """Changes the robot speed (in mm/s)"""   670         """Changes the robot acceleration (in mm/s2)"""   674         """Changes the robot joint speed (in deg/s)"""   678         """Changes the robot joint acceleration (in deg/s2)"""   682         """Changes the zone data approach (makes the movement more smooth)"""   687         """Sets a variable (output) to a given value"""   688         if type(io_var) != str:  
   689             io_var = 
'OUT[%s]' % str(io_var)        
   690         if type(io_value) != str: 
   697         self.
addline(
'%s=%s' % (io_var, io_value))
   699     def waitDI(self, io_var, io_value, timeout_ms=-1):
   700         """Waits for an input io_var to attain a given value io_value. Optionally, a timeout can be provided."""   701         if type(io_var) != str:  
   702             io_var = 
'IN[%s]' % str(io_var)        
   703         if type(io_value) != str: 
   711             self.
addline(
'WAIT FOR %s==%s' % (io_var, io_value))
   713             self.
addline(
'WAIT FOR %s==%s TIMEOUT=%.1f' % (io_var, io_value, timeout_ms))   
   715     def RunCode(self, code, is_function_call = False):
   716         """Adds code or a function call"""   719             code.replace(
' ',
'_')
   720             if not code.endswith(
')'):
   724             self.
addline(
'//call prog:%s' % code)
   729         """Display a message in the robot controller screen (teach pendant)"""   734             self.
addline(
'popUpMsg("%s")' % message)
   738         """Add a program line"""   742         """Add a log message"""   743         self.
LOG = self.
LOG + newline + 
'\n'   757             progname = progname + (
'%i' % (nprogs+1))
   760         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))
   789     [x,y,z,r,p,w] = xyzrpw
   799     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]])
   802     """Test the post with a basic program"""   806     robot.ProgStart(
"Program")
   807     robot.RunMessage(
"Program generated by RoboDK using a custom post processor", 
True)
   808     robot.setFrame(
Pose([807.766544, -963.699898, 41.478944, 0, 0, 0]))
   809     robot.setTool(
Pose([62.5, -108.253175, 100, -60, 90, 0]))
   810     robot.MoveJ(
Pose([200, 200, 500, 180, 0, 180]), [-46.18419, -6.77518, -20.54925, 71.38674, 49.58727, -302.54752] )
   811     robot.MoveL(
Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
   812     robot.MoveL(
Pose([200, 200, 262.132034, 180, 0, -150]), [-43.73892, -3.91728, -35.77935, 58.57566, 54.11615, -253.81122] )
   813     robot.RunMessage(
"Setting air valve 1 on")
   814     robot.RunCode(
"TCP_On", 
True)
   816     robot.MoveL(
Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
   817     robot.MoveL(
Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
   818     robot.MoveL(
Pose([250, 250, 191.421356, 180, 0, -150]), [-39.75778, -1.04537, -40.37883, 52.09118, 54.15317, -246.94403] )
   819     robot.RunMessage(
"Setting air valve off")
   820     robot.RunCode(
"TCP_Off", 
True)
   822     robot.MoveL(
Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
   823     robot.MoveL(
Pose([250, 200, 278.023897, 180, 0, -150]), [-41.85389, -1.95619, -34.89154, 57.43912, 52.34162, -253.73403] )
   824     robot.MoveL(
Pose([250, 150, 191.421356, 180, 0, -150]), [-43.82111, 3.29703, -40.29493, 56.02402, 56.61169, -249.23532] )
   825     robot.ProgFinish(
"Program")
   827     print(robot.PROG_PGX)
   828     if len(robot.LOG) > 0:
   829         mbox(
'Program generation LOG:\n\n' + robot.LOG)
   831     input(
"Press Enter to close...")
   833 if __name__ == 
"__main__":
   834     """Function to call when the module is executed by itself: test""" 
def setTool(self, pose, tool_id=None, tool_name=None)
def RunCode(self, code, is_function_call=False)
def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None)
def MoveJ(self, pose, joints, conf_RLF=None)
def setSpeed(self, speed_mms)
def ProgSave(self, folder, progname, ask_user=False, show_result=False)
def setZoneData(self, zone_mm)
def __init__(self, robotpost=None, robotname=None, robot_axes=6, kwargs)
def MoveL(self, pose, joints, conf_RLF=None)
def ProgStart(self, progname)
def control_ProgSize(self)
def setAccelerationJoints(self, accel_degss)
def RemoveDirFTP(self, ftp, path)
def mbox(msg, b1='OK', b2='Cancel', frame=True, t=False, entry=None)
def ProgSendRobot(self, robot_ip, remote_path, ftp_user, ftp_pass)
def UploadFTP(self, localpath)
def ProgFinish(self, progname)
def setSpeedJoints(self, speed_degs)
def addlog(self, newline)
def waitDI(self, io_var, io_value, timeout_ms=-1)
def getSaveFolder(strdir='C:\\', strtitle='Save program folder ...')
def setAcceleration(self, accel_mmss)
def setFrame(self, pose, frame_id=None, frame_name=None)
def RunMessage(self, message, iscomment=False)
def setDO(self, io_var, io_value)
def addline(self, newline)