Diff of /URBasic/urScript.py [000000] .. [c1b1c5]

Switch to unified view

a b/URBasic/urScript.py
1
'''
2
Python 3.x library to control an UR robot through its TCP/IP interfaces
3
Copyright (C) 2017  Martin Huus Bjerge, Rope Robotics ApS, Denmark
4
5
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
6
and associated documentation files (the "Software"), to deal in the Software without restriction,
7
including without limitation the rights to use, copy, modify, merge, publish, distribute,
8
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
9
is furnished to do so, subject to the following conditions:
10
11
The above copyright notice and this permission notice shall be included in all copies
12
or substantial portions of the Software.
13
14
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
16
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL "Rope Robotics ApS" BE LIABLE FOR ANY CLAIM,
17
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
20
Except as contained in this notice, the name of "Rope Robotics ApS" shall not be used
21
in advertising or otherwise to promote the sale, use or other dealings in this Software
22
without prior written authorization from "Rope Robotics ApS".
23
'''
24
import ctypes
25
__author__ = "Martin Huus Bjerge"
26
__copyright__ = "Copyright 2017, Rope Robotics ApS, Denmark"
27
__license__ = "MIT License"
28
29
import URBasic
30
import numpy as np
31
import time
32
33
class UrScript(object):
34
    '''
35
    Interface to remote access UR script commands.
36
    For more details see the script manual at this site:
37
    http://www.universal-robots.com/download/
38
39
    Beside the implementation of the script interface, this class also inherits from the
40
    Real Time Client and RTDE interface and thereby also open a connection to these data interfaces.
41
    The Real Time Client in this version is only used to send program and script commands
42
    to the robot, not to read data from the robot, all data reading is done via the RTDE interface.
43
44
    The constructor takes a UR robot hostname as input, and a RTDE configuration file, and optional a logger object.
45
46
    Input parameters:
47
    host (string):  hostname or IP of UR Robot (RT CLient server)
48
    rtde_conf_filename (string):  Path to xml file describing what channels to activate
49
    logger (URBasis_DataLogging obj): A instance if a logger object if common logging is needed.
50
51
52
    Example:
53
    rob = URBasic.urScript.UrScript('192.168.56.101', rtde_conf_filename='rtde_configuration.xml')
54
    self.close_rtc()
55
    '''
56
57
58
    def __init__(self, host, robotModel, hasForceTorque=False, conf_filename=None):
59
        '''
60
        Constructor see class description for more info.
61
        '''
62
        logger = URBasic.dataLogging.DataLogging()
63
        name = logger.AddEventLogging(__name__)
64
        self.__logger = logger.__dict__[name]
65
        self.robotConnector = URBasic.robotConnector.RobotConnector(robotModel, host, hasForceTorque, conf_filename=conf_filename)
66
        #time.sleep(200)
67
        while(self.robotConnector.RobotModel.ActualTCPPose() is None):      ## check paa om vi er startet
68
            print("waiting for everything to be ready")
69
            time.sleep(1)
70
        self.__logger.info('Init done')
71
#############   Module motion   ###############
72
73
    def waitRobotIdleOrStopFlag(self):
74
75
        while(self.robotConnector.RobotModel.RuntimeState() and not self.robotConnector.RobotModel.StopRunningFlag()):
76
            time.sleep(0.002)
77
78
        if self.robotConnector.RobotModel.rtcProgramExecutionError:
79
80
            print('Robot program execution error!!!')
81
            #raise RuntimeError('Robot program execution error!!!')
82
83
    def movej(self, q=None, a=1.4, v =1.05, t =0, r =0, wait=True, pose=None):
84
        '''
85
        Move to position (linear in joint-space) When using this command, the
86
        robot must be at standstill or come from a movej og movel with a
87
        blend. The speed and acceleration parameters controls the trapezoid
88
        speed profile of the move. The $t$ parameters can be used in stead to
89
        set the time for this move. Time setting has priority over speed and
90
        acceleration settings. The blend radius can be set with the $r$
91
        parameters, to avoid the robot stopping at the point. However, if he
92
        blend region of this mover overlaps with previous or following regions,
93
        this move will be skipped, and an 'Overlapping Blends' warning
94
        message will be generated.
95
        Parameters:
96
        q:    joint positions (Can also be a pose)
97
        a:    joint acceleration of leading axis [rad/s^2]
98
        v:    joint speed of leading axis [rad/s]
99
        t:    time [S]
100
        r:    blend radius [m]
101
        wait: function return when movement is finished
102
        pose: target pose
103
        '''
104
        prg =  '''def move_j():
105
{movestr}
106
end
107
'''
108
        movestr = self._move(movetype='j', pose=pose, a=a, v=v, t=t, r=r, wait=wait, q=q)
109
110
        programString = prg.format(**locals())
111
112
        self.robotConnector.RealTimeClient.SendProgram(programString)
113
        if(wait):
114
            self.waitRobotIdleOrStopFlag()
115
116
    def movel(self, pose=None, a=0.1, v =0.1, t =0, r =0, wait=True, q=None):
117
        '''
118
        Move to position (linear in tool-space)
119
        See movej.
120
        Parameters:
121
        pose: target pose (Can also be a joint position)
122
        a:    tool acceleration [m/s^2]
123
        v:    tool speed [m/s]
124
        t:    time [S]
125
        r:    blend radius [m]
126
        wait: function return when movement is finished
127
        q:    joint position
128
        '''
129
130
        prg =  '''def move_l():
131
{movestr}
132
end
133
'''
134
        movestr = self._move(movetype='l', pose=pose, a=a, v=v, t=t, r=r, wait=wait, q=q)
135
136
        programString = prg.format(**locals())
137
138
        self.robotConnector.RealTimeClient.SendProgram(programString)
139
        #time.sleep(0.5)
140
        if(wait):
141
            self.waitRobotIdleOrStopFlag()
142
143
144
145
    def movep(self, pose=None, a=1.2, v =0.25, r =0, wait=True, q=None):
146
        '''
147
        Move Process
148
149
        Blend circular (in tool-space) and move linear (in tool-space) to
150
        position. Accelerates to and moves with constant tool speed v.
151
        Parameters:
152
        pose: list of target pose (pose can also be specified as joint
153
              positions, then forward kinematics is used to calculate the corresponding pose)
154
        a:    tool acceleration [m/s^2]
155
        v:    tool speed [m/s]
156
        r:    blend radius [m]
157
        wait: function return when movement is finished
158
        q:    list of target joint positions
159
        '''
160
161
        prg =  '''def move_p():
162
{movestr}
163
end
164
'''
165
        movestr = self._move(movetype='p', pose=pose, a=a, v=v, t=0, r=r, wait=wait, q=q)
166
        programString = prg.format(**locals())
167
168
        self.robotConnector.RealTimeClient.SendProgram(programString)
169
        if(wait):
170
            self.waitRobotIdleOrStopFlag()
171
172
173
    def movec(self, pose_via=None, pose_to=None, a=1.2, v =0.25, r =0, wait=True, q_via=None, q_to=None):
174
        '''
175
        Move Circular: Move to position (circular in tool-space)
176
177
        TCP moves on the circular arc segment from current pose, through pose via to pose to.
178
        Accelerates to and moves with constant tool speed v.
179
180
        Parameters:
181
        pose_via: path point (note: only position is used). (pose via can also be specified as joint positions,
182
                  then forward kinematics is used to calculate the corresponding pose)
183
        pose_to:  target pose (pose to can also be specified as joint positions, then forward kinematics
184
                  is used to calculate the corresponding pose)
185
        a:        tool acceleration [m/s^2]
186
        v:        tool speed [m/s]
187
        r:        blend radius (of target pose) [m]
188
        wait:     function return when movement is finished
189
        q_via:    list of via joint positions
190
        q_to:     list of target joint positions
191
        '''
192
193
        prg =  '''def move_p():
194
{movestr}
195
end
196
'''
197
        movestr = self._move(movetype='p', pose=pose_to, a=a, v=v, t=0, r=r, wait=wait, q=q_to,pose_via=pose_via, q_via=q_via)
198
199
        programString = prg.format(**locals())
200
201
        self.robotConnector.RealTimeClient.SendProgram(programString)
202
        if(wait):
203
            self.waitRobotIdleOrStopFlag()
204
205
206
207
    def _move(self, movetype, pose=None, a=0.1, v=0.25, t=0, r=0, wait=True, q=None, pose_via=None, q_via=None):
208
        '''
209
        General move Process
210
211
        Blend circular (in tool-space) and move linear (in tool-space) to
212
        position. Accelerates to and moves with constant tool speed v.
213
        Parameters:
214
        movetype: j, l, p, c
215
        pose: list of target pose (pose can also be specified as joint
216
              positions, then forward kinematics is used to calculate the corresponding pose)
217
        a:    tool acceleration [m/s^2]
218
        v:    tool speed [m/s]
219
        r:    blend radius [m]
220
        wait: function return when movement is finished
221
        q:    list of target joint positions
222
        '''
223
224
        prefix="p"
225
        t_val=''
226
        pose_via_val=''
227
        if pose is None:
228
            prefix=""
229
            pose=q
230
        pose = np.array(pose)
231
        if movetype == 'j' or movetype == 'l':
232
            tval='t={t},'.format(**locals())
233
234
        if movetype =='c':
235
            if pose_via is None:
236
                prefix_via=""
237
                pose_via=q_via
238
            else:
239
                prefix_via="p"
240
241
            pose_via = np.array(pose_via)
242
243
            #Check if pose and pose_via have same shape
244
            if (pose.shape != pose_via.shape):
245
                return False
246
247
        movestr = ''
248
        if np.size(pose.shape)==2:
249
            for idx in range(np.size(pose, 0)):
250
                posex = np.round(pose[idx], 4)
251
                posex = posex.tolist()
252
                if movetype =='c':
253
                    pose_via_x = np.round(pose_via[idx], 4)
254
                    pose_via_x = pose_via_x.tolist()
255
                    pose_via_val='{prefix_via}{pose_via_x},'
256
257
                if (np.size(pose, 0)-1)==idx:
258
                    r=0
259
                movestr +=  '    move{movetype}({pose_via_val} {prefix}{posex}, a={a}, v={v}, {t_val} r={r})\n'.format(**locals())
260
261
            movestr +=  '    stopl({a})\n'.format(**locals())
262
        else:
263
            posex = np.round(pose, 4)
264
            posex = posex.tolist()
265
            if movetype =='c':
266
                pose_via_x = np.round(pose_via, 4)
267
                pose_via_x = pose_via_x.tolist()
268
                pose_via_val='{prefix_via}{pose_via_x},'
269
            movestr +=  '    move{movetype}({pose_via_val} {prefix}{posex}, a={a}, v={v}, {t_val} r={r})\n'.format(**locals())
270
271
272
273
        return movestr
274
275
    def force_mode(self, task_frame=[0.,0.,0., 0.,0.,0.], selection_vector=[0,0,1,0,0,0], wrench=[0.,0.,0., 0.,0.,0.], f_type=2, limits=[2, 2, 1.5, 1, 1, 1], wait=False, timeout=60):
276
        '''
277
        Set robot to be controlled in force mode
278
279
        Parameters:
280
        task frame: A pose vector that defines the force frame relative to the base frame.
281
282
        selection vector: A 6d vector that may only contain 0 or 1. 1 means that the robot will be
283
                          compliant in the corresponding axis of the task frame, 0 means the robot is
284
                          not compliant along/about that axis.
285
286
        wrench: The forces/torques the robot is to apply to its environment. These values
287
                have different meanings whether they correspond to a compliant axis or not.
288
                Compliant axis: The robot will adjust its position along/about the axis in order
289
                to achieve the specified force/torque. Non-compliant axis: The robot follows
290
                the trajectory of the program but will account for an external force/torque
291
                of the specified value.
292
293
        f_type: An integer specifying how the robot interprets the force frame.
294
                1: The force frame is transformed in a way such that its y-axis is aligned with a vector
295
                   pointing from the robot tcp towards the origin of the force frame.
296
                2: The force frame is not transformed.
297
                3: The force frame is transformed in a way such that its x-axis is the projection of
298
                   the robot tcp velocity vector onto the x-y plane of the force frame.
299
                All other values of f_type are invalid.
300
301
        limits: A 6d vector with float values that are interpreted differently for
302
                compliant/non-compliant axes:
303
                Compliant axes: The limit values for compliant axes are the maximum
304
                                allowed tcp speed along/about the axis.
305
                Non-compliant axes: The limit values for non-compliant axes are the
306
                                    maximum allowed deviation along/about an axis between the
307
                                    actual tcp position and the one set by the program.
308
309
        '''
310
        prg = '''def ur_force_mode():
311
        while True:
312
            force_mode(p{task_frame}, {selection_vector}, {wrench}, {f_type}, {limits})
313
            sync()
314
        end
315
end
316
'''
317
318
        programString = prg.format(**locals())
319
320
        self.robotConnector.RealTimeClient.SendProgram(programString)
321
        if(wait):
322
            self.waitRobotIdleOrStopFlag()
323
324
    def end_force_mode(self, wait=False):
325
        '''
326
        Resets the robot mode from force mode to normal operation.
327
        This is also done when a program stops.
328
        '''
329
        prg = 'end_force_mode()\n'
330
        programString = prg.format(**locals())
331
332
        self.robotConnector.RealTimeClient.Send(programString)                      ##### ToDo - check if send or sendprogram
333
        if(wait):
334
            self.waitRobotIdleOrStopFlag()
335
        time.sleep(0.05)
336
337
    def servoc(self, pose, a=1.2, v =0.25, r =0, wait=True):
338
        '''
339
        Servo Circular
340
        Servo to position (circular in tool-space). Accelerates to and moves with constant tool speed v.
341
342
        Parameters:
343
        pose: target pose
344
        a:    tool acceleration [m/s^2]
345
        v:    tool speed [m/s]
346
        r:    blend radius (of target pose) [m]
347
        '''
348
        prg = 'servoc(p{pose}, {a}, {v}, {r})\n'
349
350
        programString = prg.format(**locals())
351
352
        self.robotConnector.RealTimeClient.Send(programString)
353
        if(wait):
354
            self.waitRobotIdleOrStopFlag()
355
356
    def servoj(self, q, t =0.008, lookahead_time=0.1, gain=100, wait=True):
357
        '''
358
        Servo to position (linear in joint-space)
359
        Servo function used for online control of the robot. The lookahead time
360
        and the gain can be used to smoothen or sharpen the trajectory.
361
        Note: A high gain or a short lookahead time may cause instability.
362
        Prefered use is to call this function with a new setpoint (q) in each time
363
        step (thus the default t=0.008)
364
        Parameters:
365
        q:              joint positions [rad]
366
        t:              time where the command is controlling
367
                        the robot. The function is blocking for time t [S]
368
        lookahead_time: time [S], range [0.03,0.2] smoothens the trajectory with this lookahead time
369
        gain:           proportional gain for following target position, range [100,2000]
370
        '''
371
        prg = 'servoj({q}, 0.5, 0.5, {t}, {lookahead_time}, {gain})\n'
372
        programString = prg.format(**locals())
373
374
        self.robotConnector.RealTimeClient.Send(programString)
375
        if(wait):
376
            self.waitRobotIdleOrStopFlag()
377
378
    def speedj(self, qd, a, t , wait=True):
379
        '''
380
        Joint speed
381
        Accelerate linearly in joint space and continue with constant joint
382
        speed. The time t is optional; if provided the function will return after
383
        time t, regardless of the target speed has been reached. If the time t is
384
        not provided, the function will return when the target speed is reached.
385
        Parameters:
386
        qd: joint speeds [rad/s]
387
        a:  joint acceleration [rad/s^2] (of leading axis)
388
        t:  time [s] before the function returns (optional)
389
        '''
390
        prg = 'speedj({qd}, {a}, {t})\n'
391
        programString = prg.format(**locals())
392
393
        self.robotConnector.RealTimeClient.Send(programString)
394
        if(wait):
395
            self.waitRobotIdleOrStopFlag()
396
397
    def stopj(self, a, wait=True):
398
        '''
399
        Stop (linear in joint space)
400
        Decellerate joint speeds to zero
401
        Parameters
402
        a: joint acceleration [rad/s^2] (of leading axis)
403
        '''
404
        prg = 'stopj({a})\n'
405
        programString = prg.format(**locals())
406
407
        self.robotConnector.RealTimeClient.Send(programString)
408
        if(wait):
409
            self.waitRobotIdleOrStopFlag()
410
411
    def speedl(self, xd, a=1.4, t=0, aRot=None, wait=True):
412
        '''
413
        Tool speed
414
        Accelerate linearly in Cartesian space and continue with constant tool
415
        speed. The time t is optional; if provided the function will return after
416
        time t, regardless of the target speed has been reached. If the time t is
417
        not provided, the function will return when the target speed is reached.
418
        Parameters:
419
        xd:   tool speed [m/s] (spatial vector)
420
        a:    tool position acceleration [m/s^2]
421
        t:    time [s] before function returns (optional)
422
        aRot: tool acceleration [rad/s^2] (optional), if not defined a, position acceleration, is used
423
        '''
424
        if aRot is None:
425
            aRot=a
426
        prg = '''def ur_speedl():
427
    while(True):
428
        speedl({xd}, {a}, {t}, {aRot})
429
    end
430
end
431
'''
432
        programString = prg.format(**locals())
433
434
        self.robotConnector.RealTimeClient.SendProgram(programString)
435
#         prg = 'speedl({xd}, {a}, {t}, {aRot})\n'
436
#         programString = prg.format(**locals())
437
#
438
#         self.robotConnector.RealTimeClient.Send(programString)
439
        if(wait):
440
            self.waitRobotIdleOrStopFlag()
441
442
    def stopl(self, a=0.5, wait=True):
443
        '''
444
        Stop (linear in tool space)
445
        Decellerate tool speed to zero
446
        Parameters:
447
        a:    tool accleration [m/s^2]
448
        '''
449
        prg = 'stopl({a})\n'
450
        programString = prg.format(**locals())
451
452
        self.robotConnector.RealTimeClient.Send(programString)
453
        if(wait):
454
            self.waitRobotIdleOrStopFlag()
455
456
    def freedrive_mode(self, wait=False):
457
        '''
458
        Set robot in freedrive mode. In this mode the robot can be moved around by hand in the
459
        same way as by pressing the "freedrive" button.
460
        The robot will not be able to follow a trajectory (eg. a movej) in this mode.
461
        '''
462
        prg = '''def ur_freedrive_mode():
463
    while(True):
464
        freedrive_mode()
465
        sleep(600)
466
    end
467
end
468
'''
469
        programString = prg.format(**locals())
470
471
        self.robotConnector.RealTimeClient.SendProgram(programString)
472
        if(wait):
473
            self.waitRobotIdleOrStopFlag()
474
475
    def end_freedrive_mode(self, wait=True):
476
        '''
477
        Set robot back in normal position control mode after freedrive mode.
478
        '''
479
        prg = 'end_freedrive_mode()\n'
480
        programString = prg.format(**locals())
481
482
        self.robotConnector.RealTimeClient.Send(programString)
483
        if(wait):
484
            self.waitRobotIdleOrStopFlag()
485
        time.sleep(0.05)
486
487
    def teach_mode(self, wait=True):
488
        '''
489
        Set robot in freedrive mode. In this mode the robot can be moved
490
        around by hand in the same way as by pressing the "freedrive" button.
491
        The robot will not be able to follow a trajectory (eg. a movej) in this mode.
492
        '''
493
        prg = '''def ur_teach_mode():
494
    while True:
495
        teach_mode()
496
    end
497
end
498
'''
499
        programString = prg.format(**locals())
500
501
        self.robotConnector.RealTimeClient.SendProgram(programString)
502
        if(wait):
503
            self.waitRobotIdleOrStopFlag()
504
505
    def end_teach_mode(self, wait=True):
506
        '''
507
        Set robot back in normal position control mode after freedrive mode.
508
        '''
509
        prg = 'end_teach_mode()\n'
510
        programString = prg.format(**locals())
511
512
        self.robotConnector.RealTimeClient.Send(programString)
513
        if(wait):
514
            self.waitRobotIdleOrStopFlag()
515
        time.sleep(0.05)
516
517
    def conveyor_pulse_decode(self, in_type, A, B, wait=True):
518
        '''
519
        Tells the robot controller to treat digital inputs number A and B as pulses
520
        for a conveyor encoder. Only digital input 0, 1, 2 or 3 can be used.
521
522
        >>> conveyor pulse decode(1,0,1)
523
524
        This example shows how to set up quadrature pulse decoding with
525
        input A = digital in[0] and input B = digital in[1]
526
527
        >>> conveyor pulse decode(2,3)
528
529
        This example shows how to set up rising and falling edge pulse
530
        decoding with input A = digital in[3]. Note that you do not have to set
531
        parameter B (as it is not used anyway).
532
        Parameters:
533
            in_type: An integer determining how to treat the inputs on A
534
                  and B
535
                  0 is no encoder, pulse decoding is disabled.
536
                  1 is quadrature encoder, input A and B must be
537
                    square waves with 90 degree offset. Direction of the
538
                    conveyor can be determined.
539
                  2 is rising and falling edge on single input (A).
540
                  3 is rising edge on single input (A).
541
                  4 is falling edge on single input (A).
542
543
            The controller can decode inputs at up to 40kHz
544
            A: Encoder input A, values of 0-3 are the digital inputs 0-3.
545
            B: Encoder input B, values of 0-3 are the digital inputs 0-3.
546
        '''
547
548
        prg = 'conveyor_pulse_decode({in_type}, {A}, {B})\n'
549
        programString = prg.format(**locals())
550
551
        self.robotConnector.RealTimeClient.Send(programString)
552
        if(wait):
553
            self.waitRobotIdleOrStopFlag()
554
555
    def set_conveyor_tick_count(self, tick_count, absolute_encoder_resolution=0, wait=True):
556
        '''
557
        Tells the robot controller the tick count of the encoder. This function is
558
        useful for absolute encoders, use conveyor pulse decode() for setting
559
        up an incremental encoder. For circular conveyors, the value must be
560
        between 0 and the number of ticks per revolution.
561
        Parameters:
562
        tick_count: Tick count of the conveyor (Integer)
563
        absolute_encoder_resolution: Resolution of the encoder, needed to
564
                                     handle wrapping nicely.
565
                                     (Integer)
566
                                    0 is a 32 bit signed encoder, range [-2147483648 ;2147483647] (default)
567
                                    1 is a 8 bit unsigned encoder, range [0 ; 255]
568
                                    2 is a 16 bit unsigned encoder, range [0 ; 65535]
569
                                    3 is a 24 bit unsigned encoder, range [0 ; 16777215]
570
                                    4 is a 32 bit unsigned encoder, range [0 ; 4294967295]
571
        '''
572
        prg = 'set_conveyor_tick_count({tick_count}, {absolute_encoder_resolution})\n'
573
        programString = prg.format(**locals())
574
575
        self.robotConnector.RealTimeClient.Send(programString)
576
        if(wait):
577
            self.waitRobotIdleOrStopFlag()
578
579
    def get_conveyor_tick_count(self):
580
        '''
581
        Tells the tick count of the encoder, note that the controller interpolates tick counts to get
582
        more accurate movements with low resolution encoders
583
584
        Return Value:
585
            The conveyor encoder tick count
586
        '''
587
588
        prg = '''def ur_get_conveyor_tick_count():
589
    write_output_float_register(0, get_conveyor_tick_count())
590
end
591
'''
592
        programString = prg.format(**locals())
593
594
        self.robotConnector.RealTimeClient.SendProgram(programString)
595
        self.waitRobotIdleOrStopFlag()
596
        return self.robotConnector.RobotModel.outputDoubleRegister[0]
597
598
    def stop_conveyor_tracking(self, a=15, aRot ='a', wait=True):
599
        '''
600
        Stop tracking the conveyor, started by track conveyor linear() or
601
        track conveyor circular(), and decellerate tool speed to zero.
602
        Parameters:
603
        a:    tool accleration [m/s^2] (optional)
604
        aRot: tool acceleration [rad/s^2] (optional), if not defined a, position acceleration, is used
605
        '''
606
        prg = 'stop_conveyor_tracking({a}, {aRot})\n'
607
608
        programString = prg.format(**locals())
609
610
        self.robotConnector.RealTimeClient.Send(programString)
611
        if(wait):
612
            self.waitRobotIdleOrStopFlag()
613
614
615
    def track_conveyor_circular(self, center, ticks_per_revolution, rotate_tool, wait=True):
616
        '''
617
        Makes robot movement (movej() etc.) track a circular conveyor.
618
619
        >>> track conveyor circular(p[0.5,0.5,0,0,0,0],500.0, false)
620
621
        The example code makes the robot track a circular conveyor with
622
        center in p[0.5,0.5,0,0,0,0] of the robot base coordinate system, where
623
        500 ticks on the encoder corresponds to one revolution of the circular
624
        conveyor around the center.
625
        Parameters:
626
        center:               Pose vector that determines the center the conveyor in the base
627
                              coordinate system of the robot.
628
        ticks_per_revolution: How many tichs the encoder sees when the conveyor moves one revolution.
629
        rotate tool:          Should the tool rotate with the coneyor or stay in the orientation
630
                              specified by the trajectory (movel() etc.).
631
        '''
632
        prg = 'track_conveyor_circular({center}, {ticks_per_revolution}, {rotate_tool})\n'
633
634
        programString = prg.format(**locals())
635
636
        self.robotConnector.RealTimeClient.Send(programString)
637
        if(wait):
638
            self.waitRobotIdleOrStopFlag()
639
640
641
642
    def track_conveyor_linear(self, direction, ticks_per_meter, wait=True):
643
        '''
644
        Makes robot movement (movej() etc.) track a linear conveyor.
645
646
        >>> track conveyor linear(p[1,0,0,0,0,0],1000.0)
647
648
        The example code makes the robot track a conveyor in the x-axis of
649
        the robot base coordinate system, where 1000 ticks on the encoder
650
        corresponds to 1m along the x-axis.
651
        Parameters:
652
        direction:       Pose vector that determines the direction of the conveyor in the base
653
                         coordinate system of the robot
654
        ticks per meter: How many tichs the encoder sees when the conveyor moves one meter
655
        '''
656
        prg = 'track_conveyor_linear({direction}, {ticks_per_meter})\n'
657
658
        programString = prg.format(**locals())
659
660
        self.robotConnector.RealTimeClient.Send(programString)
661
        if(wait):
662
            self.waitRobotIdleOrStopFlag()
663
664
    def position_deviation_warning(self, enabled, threshold =0.8, wait=True):
665
        '''
666
        Write a message to the log when the robot position deviates from the target position.
667
        Parameters:
668
        enabled:   enable or disable position deviation log messages (Boolean)
669
        threshold: (optional) should be a ratio in the range ]0;1], where 0 is no position deviation and 1 is the
670
                   position deviation that causes a protective stop (Float).
671
        '''
672
        prg = 'position_deviation_warning({enabled}, {threshold})\n'
673
674
        programString = prg.format(**locals())
675
676
        self.robotConnector.RealTimeClient.Send(programString)
677
        if(wait):
678
            self.waitRobotIdleOrStopFlag()
679
680
    def reset_revolution_counter(self, qNear=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0], wait=True):
681
        '''
682
        Reset the revolution counter, if no offset is specified. This is applied on
683
        joints which safety limits are set to "Unlimited" and are only applied
684
        when new safety settings are applied with limitted joint angles.
685
686
        >>> reset revolution counter()
687
688
        Parameters:
689
        qNear: Optional parameter, reset the revolution counter to one close to the given qNear joint vector.
690
               If not defined, the joint's actual number of revolutions are used.
691
        '''
692
        prg = 'reset_revolution_counter(qNear)\n'
693
694
        programString = prg.format(**locals())
695
696
        self.robotConnector.RealTimeClient.Send(programString)
697
        if(wait):
698
            self.waitRobotIdleOrStopFlag()
699
700
    def set_pos(self, q, wait=True):
701
        '''
702
        Set joint positions of simulated robot
703
        Parameters
704
        q: joint positions
705
        '''
706
        prg = 'set_pos({q})\n'
707
708
        programString = prg.format(**locals())
709
710
        self.robotConnector.RealTimeClient.Send(programString)
711
        if(wait):
712
            self.waitRobotIdleOrStopFlag()
713
714
####################   Module internals    ####################
715
716
    def force(self, wait=True):
717
        '''
718
        Returns the force exerted at the TCP
719
720
        Return the current externally exerted force at the TCP. The force is the
721
        norm of Fx, Fy, and Fz calculated using get tcp force().
722
        Return Value
723
        The force in Newtons (float)
724
        '''
725
        if(wait):
726
            self.sync()
727
        return self.robotConnector.RobotModel.TcpForceScalar()
728
729
730
    def get_actual_joint_positions(self, wait=True):
731
        '''
732
        Returns the actual angular positions of all joints
733
734
        The angular actual positions are expressed in radians and returned as a
735
        vector of length 6. Note that the output might differ from the output of
736
        get target joint positions(), especially durring acceleration and heavy
737
        loads.
738
739
        Return Value:
740
        The current actual joint angular position vector in rad : [Base,
741
        Shoulder, Elbow, Wrist1, Wrist2, Wrist3]
742
        '''
743
        if(wait):
744
            self.sync()
745
        return self.robotConnector.RobotModel.ActualQ()
746
        c_pose = self.robotConnector.RobotModel.ActualQ
747
748
        pose = []
749
        pose.append(ctypes.c_double(c_pose[0]).value)
750
        pose.append(ctypes.c_double(c_pose[1]).value)
751
        pose.append(ctypes.c_double(c_pose[2]).value)
752
        pose.append(ctypes.c_double(c_pose[3]).value)
753
        pose.append(ctypes.c_double(c_pose[4]).value)
754
        pose.append(ctypes.c_double(c_pose[5]).value)
755
        return pose
756
757
758
759
    def get_actual_joint_speeds(self, wait=True):
760
        '''
761
        Returns the actual angular velocities of all joints
762
763
        The angular actual velocities are expressed in radians pr. second and
764
        returned as a vector of length 6. Note that the output might differ from
765
        the output of get target joint speeds(), especially durring acceleration
766
        and heavy loads.
767
768
        Return Value
769
        The current actual joint angular velocity vector in rad/s:
770
        [Base, Shoulder, Elbow, Wrist1, Wrist2, Wrist3]
771
        '''
772
        if(wait):
773
            self.sync()
774
        return self.robotConnector.RobotModel.ActualQD
775
776
777
    def get_actual_tcp_pose(self, wait=True):
778
        '''
779
        Returns the current measured tool pose
780
781
        Returns the 6d pose representing the tool position and orientation
782
        specified in the base frame. The calculation of this pose is based on
783
        the actual robot encoder readings.
784
785
        Return Value
786
        The current actual TCP vector : ([X, Y, Z, Rx, Ry, Rz])
787
        '''
788
        if(wait):
789
            self.sync()
790
        return self.robotConnector.RobotModel.ActualTCPPose()
791
        c_pose = self.robotConnector.RobotModel.ActualTCPPose
792
793
        pose = []
794
        pose.append(ctypes.c_double(c_pose[0]).value)
795
        pose.append(ctypes.c_double(c_pose[1]).value)
796
        pose.append(ctypes.c_double(c_pose[2]).value)
797
        pose.append(ctypes.c_double(c_pose[3]).value)
798
        pose.append(ctypes.c_double(c_pose[4]).value)
799
        pose.append(ctypes.c_double(c_pose[5]).value)
800
        return pose
801
802
803
    def get_actual_tcp_speed(self,wait=True):
804
        '''
805
        Returns the current measured TCP speed
806
807
        The speed of the TCP retuned in a pose structure. The first three values
808
        are the cartesian speeds along x,y,z, and the last three define the
809
        current rotation axis, rx,ry,rz, and the length |rz,ry,rz| defines the angular
810
        velocity in radians/s.
811
        Return Value
812
        The current actual TCP velocity vector; ([X, Y, Z, Rx, Ry, Rz])
813
        '''
814
        if(wait):
815
            self.sync()
816
817
        return self.robotConnector.RobotModel.ActualTCPSpeed()
818
819
    def get_actual_tool_flange_pose(self):
820
        '''
821
        Returns the current measured tool flange pose
822
823
        Returns the 6d pose representing the tool flange position and
824
        orientation specified in the base frame, without the Tool Center Point
825
        offset. The calculation of this pose is based on the actual robot
826
        encoder readings.
827
828
        Return Value:
829
        The current actual tool flange vector : ([X, Y, Z, Rx, Ry, Rz])
830
831
        Note: See get actual tcp pose for the actual 6d pose including TCP offset.
832
        '''
833
        raise NotImplementedError('Function Not yet implemented')
834
835
    def get_controller_temp(self):
836
        '''
837
        Returns the temperature of the control box
838
839
        The temperature of the robot control box in degrees Celcius.
840
841
        Return Value:
842
        A temperature in degrees Celcius (float)
843
        '''
844
        raise NotImplementedError('Function Not yet implemented')
845
846
    def get_inverse_kin(self, x, qnear=None, maxPositionError =0.0001, maxOrientationError =0.0001):
847
        '''
848
        Inverse kinematic transformation (tool space -> joint space).
849
        Solution closest to current joint positions is returned, unless qnear defines one.
850
851
        Parameters:
852
        x:                   tool pose (spatial vector)
853
        qnear:               joint positions to select solution.
854
                             Optional.
855
        maxPositionError:    Define the max allowed position error.
856
                             Optional.
857
        maxOrientationError: Define the max allowed orientation error.
858
                             Optional.
859
860
        Return Value:
861
        joint positions
862
        '''
863
        # Only supply qnear if we also got a value for it
864
        if qnear:
865
            prg = '''def calculate_inverse_kin():
866
    kin = get_inverse_kin(p{x}, {qnear}, maxPositionError={maxPositionError}, maxOrientationError={maxOrientationError})
867
    write_output_float_register(0, kin[0])
868
    write_output_float_register(1, kin[1])
869
    write_output_float_register(2, kin[2])
870
    write_output_float_register(3, kin[3])
871
    write_output_float_register(4, kin[4])
872
    write_output_float_register(5, kin[5])
873
end
874
'''
875
        else:
876
            prg = '''def calculate_inverse_kin():
877
    kin = get_inverse_kin(p{x}, maxPositionError={maxPositionError}, maxOrientationError={maxOrientationError})
878
    write_output_float_register(0, kin[0])
879
    write_output_float_register(1, kin[1])
880
    write_output_float_register(2, kin[2])
881
    write_output_float_register(3, kin[3])
882
    write_output_float_register(4, kin[4])
883
    write_output_float_register(5, kin[5])
884
end
885
'''
886
        if type(x) is not list:
887
            x = x.tolist()
888
        programString = prg.format(**locals())
889
890
        self.robotConnector.RealTimeClient.SendProgram(programString)
891
        self.waitRobotIdleOrStopFlag()
892
        self.sync()
893
894
        return [
895
            self.robotConnector.RobotModel.OutputDoubleRegister(0),
896
            self.robotConnector.RobotModel.OutputDoubleRegister(1),
897
            self.robotConnector.RobotModel.OutputDoubleRegister(2),
898
            self.robotConnector.RobotModel.OutputDoubleRegister(3),
899
            self.robotConnector.RobotModel.OutputDoubleRegister(4),
900
            self.robotConnector.RobotModel.OutputDoubleRegister(5),
901
        ]
902
903
    def get_joint_temp(self,j):
904
        '''
905
        Returns the temperature of joint j
906
907
        The temperature of the joint house of joint j, counting from zero. j=0 is
908
        the base joint, and j=5 is the last joint before the tool flange.
909
910
        Parameters:
911
        j: The joint number (int)
912
913
        Return Value:
914
        A temperature in degrees Celcius (float)
915
        '''
916
        raise NotImplementedError('Function Not yet implemented')
917
918
    def get_joint_torques(self):
919
        '''
920
        Returns the torques of all joints
921
922
        The torque on the joints, corrected by the torque
923
        robot itself (gravity, friction, etc.), returned as
924
925
        Return Value:
926
        The joint torque vector in ; ([float])
927
        '''
928
        raise NotImplementedError('Function Not yet implemented')
929
930
    def get_target_joint_positions(self):
931
        '''
932
        Returns the desired angular position of all joints
933
934
        The angular target positions are expressed in radians and returned as a
935
        vector of length 6. Note that the output might differ from the output of
936
        get actual joint positions(), especially durring acceleration and heavy
937
        loads.
938
939
        Return Value:
940
        The current target joint angular position vector in rad: [Base,
941
        Shoulder, Elbow, Wrist1, Wrist2, Wrist3]
942
        '''
943
        raise NotImplementedError('Function Not yet implemented')
944
945
    def get_target_joint_speeds(self):
946
        '''
947
        Returns the desired angular velocities of all joints
948
949
        The angular target velocities are expressed in radians pr. second and
950
        returned as a vector of length 6. Note that the output might differ from
951
        the output of get actual joint speeds(), especially durring acceleration
952
        and heavy loads.
953
954
        Return Value:
955
        The current target joint angular velocity vector in rad/s:
956
        [Base, Shoulder, Elbow, Wrist1, Wrist2, Wrist3]
957
        '''
958
        raise NotImplementedError('Function Not yet implemented')
959
960
    def get_target_tcp_pose(self):
961
        '''
962
        Returns the current target tool pose
963
964
        Returns the 6d pose representing the tool position and orientation
965
        specified in the base frame. The calculation of this pose is  based on
966
        the current target joint positions.
967
968
        Return Value:
969
        The current target TCP vector; ([X, Y, Z, Rx, Ry, Rz])
970
        '''
971
        raise NotImplementedError('Function Not yet implemented')
972
973
    def get_target_tcp_speed(self):
974
        '''
975
        Returns the current target TCP speed
976
977
        The desired speed of the TCP returned in a pose structure. The first
978
        three values are the cartesian speeds along x,y,z, and the last three
979
        define the current rotation axis, rx,ry,rz, and the length |rz,ry,rz| defines
980
        the angular velocity in radians/s.
981
982
        Return Value:
983
        The TCP speed; (pose)
984
        '''
985
        raise NotImplementedError('Function Not yet implemented')
986
987
    def get_tcp_force(self, wait=True):
988
        '''
989
        Returns the wrench (Force/Torque vector) at the TCP
990
991
        The external wrench is computed based on the error between the joint
992
        torques required to stay on the trajectory and the expected joint
993
        torques. The function returns "p[Fx (N), Fy(N), Fz(N), TRx (Nm), TRy (Nm),
994
        TRz (Nm)]". where Fx, Fy, and Fz are the forces in the axes of the robot
995
        base coordinate system measured in Newtons, and TRx, TRy, and TRz
996
        are the torques around these axes measured in Newton times Meters.
997
998
        Return Value:
999
        the wrench (pose)
1000
        '''
1001
        if(wait):
1002
            self.sync()
1003
        return self.robotConnector.RobotModel.ActualTCPForce()
1004
1005
    def get_tool_accelerometer_reading(self):
1006
        '''
1007
        Returns the current reading of the tool accelerometer as a
1008
        three-dimensional vector.
1009
1010
        The accelerometer axes are aligned with the tool coordinates, and
1011
        pointing an axis upwards results in a positive reading.
1012
1013
        Return Value:
1014
        X, Y, and Z composant of the measured acceleration in
1015
        SI-units (m/s^2).
1016
        '''
1017
        raise NotImplementedError('Function Not yet implemented')
1018
1019
    def get_tool_current(self):
1020
        '''
1021
        Returns the tool current
1022
1023
        The tool current consumption measured in ampere.
1024
1025
        Return Value:
1026
        The tool current in ampere.
1027
        '''
1028
        raise NotImplementedError('Function Not yet implemented')
1029
1030
    def is_steady(self):
1031
        '''
1032
        Checks if robot is fully at rest.
1033
1034
        True when the robot is fully at rest, and ready to accept higher external
1035
        forces and torques, such as from industrial screwdrivers. It is useful in
1036
        combination with the GUI's wait node, before starting the screwdriver
1037
        or other actuators influencing the position of the robot.
1038
1039
        Note: This function will always return false in modes other than the
1040
        standard position mode, e.g. false in force and teach mode.
1041
1042
        Return Value:
1043
        True when the robot is fully at rest. Returns False otherwise
1044
        (bool)
1045
        '''
1046
        raise NotImplementedError('Function Not yet implemented')
1047
1048
    def is_within_safety_limits(self, pose):
1049
        '''
1050
        Checks if the given pose is reachable and within the current safety
1051
        limits of the robot.
1052
1053
        This check considers joint limits (if the target pose is specified as joint
1054
        positions), safety planes limits, TCP orientation deviation limits and
1055
        range of the robot. If a solution is found when applying the inverse
1056
        kinematics to the given target TCP pose, this pose is considered
1057
        reachable.
1058
1059
        Parameters:
1060
        pose: Target pose (which can also be specified as joint positions)
1061
1062
        Return Value:
1063
        True if within limits, false otherwise (bool)
1064
        '''
1065
        raise NotImplementedError('Function Not yet implemented')
1066
1067
    def popup(self, s, title='Popup', warning=False, error =False):
1068
        '''
1069
        Display popup on GUI
1070
1071
        Display message in popup window on GUI.
1072
1073
        Parameters:
1074
        s:       message string
1075
        title:   title string
1076
        warning: warning message?
1077
        error:   error message?
1078
        '''
1079
        raise NotImplementedError('Function Not yet implemented')
1080
1081
    def powerdown(self):
1082
        '''
1083
        Shutdown the robot, and power off the robot and controller.
1084
        '''
1085
        raise NotImplementedError('Function Not yet implemented')
1086
1087
    def set_gravity(self, d, wait=True):
1088
        '''
1089
        Set the direction of the acceleration experienced by the robot. When
1090
        the robot mounting is fixed, this corresponds to an accleration of g
1091
        away from the earth's centre.
1092
1093
        >>> set gravity([0, 9.82*sin(theta), 9.82*cos(theta)])
1094
1095
        will set the acceleration for a robot that is rotated "theta" radians
1096
        around the x-axis of the robot base coordinate system
1097
1098
        Parameters:
1099
        d: 3D vector, describing the direction of the gravity, relative to the base of the robot.
1100
1101
        Exampel:
1102
        set_gravity([0,0,9.82])  #Robot mounted at flore
1103
        '''
1104
1105
        prg = 'set_gravity({d})\n'
1106
1107
        programString = prg.format(**locals())
1108
1109
        self.robotConnector.RealTimeClient.Send(programString)
1110
        if(wait):
1111
            self.waitRobotIdleOrStopFlag()
1112
1113
    def set_payload(self, m, CoG):
1114
        '''
1115
        Set payload mass and center of gravity
1116
1117
        Alternatively one could use set payload mass and set payload cog.
1118
1119
        Sets the mass and center of gravity (abbr. CoG) of the payload.
1120
1121
        This function must be called, when the payload weight or weight
1122
        distribution changes - i.e when the robot picks up or puts down a
1123
        heavy workpiece.
1124
1125
        The CoG argument is optional - if not provided, the Tool Center Point
1126
        (TCP) will be used as the Center of Gravity (CoG). If the CoG argument
1127
        is omitted, later calls to set tcp(pose) will change CoG to the new TCP.
1128
1129
        The CoG is specified as a vector, [CoGx, CoGy, CoGz], displacement,
1130
        from the toolmount.
1131
1132
        Parameters:
1133
        m:   mass in kilograms
1134
        CoG: Center of Gravity: [CoGx, CoGy, CoGz] in meters.
1135
             Optional.
1136
        '''
1137
        raise NotImplementedError('Function Not yet implemented')
1138
1139
    def set_payload_cog(self, CoG, wait=True):
1140
        '''
1141
        Set center of gravity
1142
1143
        See also set payload.
1144
1145
        Sets center of gravity (abbr. CoG) of the payload.
1146
1147
        This function must be called, when the weight distribution changes - i.e
1148
        when the robot picks up or puts down a heavy workpiece.
1149
1150
        The CoG is specified as a vector, [CoGx, CoGy, CoGz], displacement,
1151
        from the toolmount.
1152
1153
        Parameters:
1154
        CoG: Center of Gravity: [CoGx, CoGy, CoGz] in meters.
1155
        '''
1156
1157
        prg = 'set_payload_cog({CoG})\n'
1158
1159
        programString = prg.format(**locals())
1160
1161
        self.robotConnector.RealTimeClient.Send(programString)
1162
        if(wait):
1163
            self.waitRobotIdleOrStopFlag()
1164
1165
1166
1167
    def set_payload_mass(self, m, wait=True):
1168
        '''
1169
        Set payload mass
1170
1171
        See also set payload.
1172
1173
        Sets the mass of the payload.
1174
1175
        This function must be called, when the payload weight changes - i.e
1176
        when the robot picks up or puts down a heavy workpiece.
1177
1178
        Parameters:
1179
        m: mass in kilograms
1180
        '''
1181
        prg = 'set_payload_mass({m})\n'
1182
1183
        programString = prg.format(**locals())
1184
1185
        self.robotConnector.RealTimeClient.Send(programString)
1186
        if(wait):
1187
            self.waitRobotIdleOrStopFlag()
1188
1189
    def set_tcp(self, pose, wait=True):
1190
        '''
1191
        Set the Tool Center Point
1192
1193
        Sets the transformation from the output flange coordinate system to
1194
        the TCP as a pose.
1195
1196
        Parameters:
1197
        pose: A pose describing the transformation.
1198
        '''
1199
1200
        if type(pose).__module__ == np.__name__:
1201
            pose = pose.tolist()
1202
        prg = 'set_tcp(p{pose})\n'
1203
1204
        programString = prg.format(**locals())
1205
1206
        self.robotConnector.RealTimeClient.Send(programString)
1207
        if(wait):
1208
            self.waitRobotIdleOrStopFlag()
1209
        time.sleep(0.05)
1210
1211
    def sleep(self, t):
1212
        '''
1213
        Sleep for an amount of time
1214
1215
        Parameters:
1216
        t: time [s]
1217
        '''
1218
        time.sleep(t)
1219
1220
    def sync(self):
1221
        '''
1222
        Uses up the remaining "physical" time a thread has in the current
1223
        frame/sample.
1224
        '''
1225
        initialRobotTime = self.robotConnector.RobotModel.RobotTimestamp()
1226
        while(self.robotConnector.RobotModel.RobotTimestamp() == initialRobotTime):
1227
            time.sleep(0.001)
1228
1229
1230
    def textmsg(self, s1, s2=''):
1231
        '''
1232
        Send text message to log
1233
1234
        Send message with s1 and s2 concatenated to be shown on the GUI
1235
        log-tab
1236
        Parameters
1237
        s1: message string, variables of other types (int, bool poses
1238
        etc.) can also be sent
1239
        s2: message string, variables of other types (int, bool poses
1240
        etc.) can also be sent
1241
        '''
1242
        raise NotImplementedError('Function Not yet implemented')
1243
1244
############    Module urmath    #################
1245
    @staticmethod
1246
    def pose_add(p_1, p_2):
1247
        '''
1248
        Pose addition
1249
1250
        Both arguments contain three position parameters (x, y, z) jointly called
1251
        P, and three rotation parameters (R x, R y, R z) jointly called R. This
1252
        function calculates the result x 3 as the addition of the given poses as
1253
        follows:
1254
        p 3.P = p 1.P + p 2.P
1255
        p 3.R = p 1.R * p 2.R
1256
1257
        Parameters
1258
        p 1: tool pose 1(pose)
1259
        p 2: tool pose 2 (pose)
1260
1261
        Return Value
1262
        Sum of position parts and product of rotation parts (pose)
1263
        '''
1264
        Trans_1 = URBasic.kinematic.Pose2Tran_Mat(p_1)
1265
        Trans_2 = URBasic.kinematic.Pose2Tran_Mat(p_2)
1266
        Trans_3 = np.matmul(Trans_1, Trans_2)
1267
        p_3 = URBasic.kinematic.Tran_Mat2Pose(Trans_3)
1268
        return p_3
1269
1270
1271
1272
1273
1274
############    Module interfaces  #################
1275
1276
    def get_configurable_digital_in(self, n):
1277
        '''
1278
        Get configurable digital input signal level
1279
1280
        See also get standard digital in and get tool digital in.
1281
1282
        Parameters:
1283
        n: The number (id) of the input, integer: [0:7]
1284
1285
        Return Value:
1286
        boolean, The signal level.
1287
        '''
1288
        return self.robotConnector.RobotModel.ConfigurableInputBits(n)
1289
1290
    def get_configurable_digital_out(self, n):
1291
        '''
1292
        Get configurable digital output signal level
1293
1294
        See also get standard digital out and get tool digital out.
1295
1296
        Parameters:
1297
        n: The number (id) of the output, integer: [0:7]
1298
1299
        Return Value:
1300
        boolean, The signal level.
1301
        '''
1302
1303
        return self.robotConnector.RobotModel.ConfigurableOutputBits(n)
1304
1305
    def get_euromap_input(self, port_number):
1306
        '''
1307
        Reads the current value of a specific Euromap67 input signal. See
1308
        http://universal-robots.com/support for signal specifications.
1309
1310
        >>> var = get euromap input(3)
1311
1312
        Parameters:
1313
        port number: An integer specifying one of the available
1314
        Euromap67 input signals.
1315
1316
        Return Value:
1317
        A boolean, either True or False
1318
        '''
1319
        raise NotImplementedError('Function Not yet implemented')
1320
1321
    def get_euromap_output(self, port_number):
1322
        '''
1323
        Reads the current value of a specific Euromap67 output signal. This
1324
        means the value that is sent from the robot to the injection moulding
1325
        machine. See http://universal-robots.com/support for signal
1326
        specifications.
1327
1328
        >>> var = get euromap output(3)
1329
1330
        Parameters:
1331
        port number: An integer specifying one of the available
1332
        Euromap67 output signals.
1333
1334
        Return Value:
1335
        A boolean, either True or False
1336
        '''
1337
        raise NotImplementedError('Function Not yet implemented')
1338
1339
    def get_flag(self, n):
1340
        '''
1341
        Flags behave like internal digital outputs. The keep information
1342
        between program runs.
1343
        Parameters
1344
        n: The number (id) of the flag, intereger: [0:32]
1345
        Return Value
1346
        Boolean, The stored bit.
1347
        '''
1348
        raise NotImplementedError('Function Not yet implemented')
1349
1350
    def get_standard_analog_in(self, n, wait=True):
1351
        '''
1352
        Get standard analog input signal level
1353
1354
        See also get tool analog in.
1355
1356
        Parameters:
1357
        n: The number (id) of the input, integer: [0:1]
1358
        wait (bool): If True, waits for next data packet before returning. (Default True)
1359
1360
        Return Value:
1361
        boolean, The signal level.
1362
        '''
1363
1364
        if(wait):
1365
            self.sync()
1366
        return self.robotConnector.RobotModel.StandardAnalogInput(n)
1367
1368
    def get_standard_analog_out(self, n, wait=True):
1369
        '''
1370
        Get standard analog output level
1371
1372
        Parameters:
1373
        n: The number (id) of the input, integer: [0:1]
1374
        wait (bool): If True, waits for next data packet before returning. (Default True)
1375
1376
        Return Value:
1377
        float, The signal level [0;1]
1378
        '''
1379
        if n == 0:
1380
            if(wait):
1381
                self.sync()
1382
            return self.robotConnector.RobotModel.StandardAnalogOutput0
1383
        elif n == 1:
1384
            if(wait):
1385
                self.sync()
1386
                return self.robotConnector.RobotModel.StandardAnalogOutput1
1387
        else:
1388
            raise KeyError('Index out of range')
1389
1390
    def get_standard_digital_in(self, n, wait=True):
1391
        '''
1392
        Get standard digital input signal level
1393
1394
        See also get configurable digital in and get tool digital in.
1395
1396
        Parameters:
1397
        n (int):     The number (id) of the input, integer: [0:7]
1398
        wait (bool): If True, waits for next data packet before returning. (Default True)
1399
1400
        Return Value:
1401
        boolean, The signal level.
1402
        '''
1403
        return self.robotConnector.RobotModel.DigitalInputBits(n)
1404
1405
    def get_standard_digital_out(self, n):
1406
        '''
1407
        Get standard digital output signal level
1408
1409
        See also get configurable digital out and get tool digital out.
1410
1411
        Parameters:
1412
        n: The number (id) of the input, integer: [0:7]
1413
1414
        Return Value:
1415
        boolean, The signal level.
1416
        '''
1417
1418
        return self.robotConnector.RobotModel.DigitalOutputBits(n)
1419
1420
1421
    def get_tool_analog_in(self, n):
1422
        '''
1423
        Get tool analog input level
1424
1425
        See also get standard analog in.
1426
1427
        Parameters:
1428
        n: The number (id) of the input, integer: [0:1]
1429
1430
        Return Value:
1431
        float, The signal level [0,1]
1432
        '''
1433
        raise NotImplementedError('Function Not yet implemented')
1434
1435
    def get_tool_digital_in(self, n):
1436
        '''
1437
        Get tool digital input signal level
1438
1439
        See also get configurable digital in and
1440
        get standard digital in.
1441
1442
        Parameters:
1443
        n: The number (id) of the input, integer: [0:1]
1444
1445
        Return Value:
1446
        boolean, The signal level.
1447
        '''
1448
        raise NotImplementedError('Function Not yet implemented')
1449
1450
    def get_tool_digital_out(self, n):
1451
        '''
1452
        Get tool digital output signal level
1453
1454
        See also get standard digital out and
1455
        get configurable digital out.
1456
1457
        Parameters:
1458
        n: The number (id) of the output, integer: [0:1]
1459
1460
        Return Value:
1461
        boolean, The signal level.
1462
        '''
1463
        raise NotImplementedError('Function Not yet implemented')
1464
1465
    def modbus_add_signal(self, IP, slave_number, signal_address, signal_type, signal_name):
1466
        '''
1467
        Adds a new modbus signal for the controller to supervise. Expects no
1468
        response.
1469
1470
        >>> modbus add signal("172.140.17.11", 255, 5, 1, "output1")
1471
        Parameters:
1472
        IP:             A string specifying the IP address of the modbus unit
1473
                        to which the modbus signal is connected.
1474
1475
        slave_number:   An integer normally not used and set to 255, but is a
1476
                        free choice between 0 and 255.
1477
1478
        signal_address: An integer specifying the address of the either the coil
1479
                        or the register that this new signal should reflect.
1480
                        Consult the configuration of the modbus unit for this information.
1481
1482
        signal_type:    An integer specifying the type of signal to add.
1483
                        0 = digital input, 1 = digital output,
1484
                        2 = register input and 3 = register output.
1485
1486
        signal_name:    A string uniquely identifying the signal.
1487
                        If a string is supplied which is equal to an already added signal,
1488
                        the new signal will replace the old one.
1489
        '''
1490
        raise NotImplementedError('Function Not yet implemented')
1491
1492
    def modbus_delete_signal(self, signal_name):
1493
        '''
1494
        Deletes the signal identified by the supplied signal name.
1495
1496
        >>> modbus delete signal("output1")
1497
1498
        Parameters:
1499
        signal_name: A string equal to the name of the signal that should be deleted.
1500
        '''
1501
        raise NotImplementedError('Function Not yet implemented')
1502
1503
    def modbus_get_signal_status(self, signal_name, is_secondary_program):
1504
        '''
1505
        Reads the current value of a specific signal.
1506
1507
        >>> modbus get signal status("output1",False)
1508
1509
        Parameters:
1510
        signal name:          A string equal to the name of the signal for which
1511
                              the value should be gotten.
1512
1513
        is_secondary_program: A boolean for interal use only.
1514
                              Must be set to False.
1515
1516
        Return Value:
1517
        An integer or a boolean. For digital signals: True or False. For
1518
        register signals: The register value expressed as an unsigned
1519
        integer.
1520
        '''
1521
        raise NotImplementedError('Function Not yet implemented')
1522
1523
    def modbus_send_custom_command(self, IP, slave_number, function_code, data):
1524
        '''
1525
        Sends a command specified by the user to the modbus unit located
1526
        on the specified IP address. Cannot be used to request data, since the
1527
        response will not be received. The user is responsible for supplying data
1528
        which is meaningful to the supplied function code. The builtin function
1529
        takes care of constructing the modbus frame, so the user should not
1530
        be concerned with the length of the command.
1531
1532
        >>> modbus send custom command("172.140.17.11",103,6,[17,32,2,88])
1533
1534
        The above example sets the watchdog timeout on a Beckhoff BK9050
1535
        to 600 ms. That is done using the modbus function code 6 (preset single
1536
        register) and then supplying the register address in the first two bytes of
1537
        the data array ([17,32] = [0x1120]) and the desired register content in
1538
        the last two bytes ([2,88] = [0x0258] = dec 600).
1539
1540
        Parameters:
1541
        IP:            A string specifying the IP address locating the modbus
1542
                       unit to which the custom command should be send.
1543
1544
        slave_number:  An integer specifying the slave number to use for the custom command.
1545
1546
        function_code: An integer specifying the function code for the custom command.
1547
1548
        data:          An array of integers in which each entry must be a valid byte (0-255) value.
1549
        '''
1550
        raise NotImplementedError('Function Not yet implemented')
1551
1552
    def modbus_set_output_register(self, signal_name, register_value, is_secondary_program):
1553
        '''
1554
        Sets the output register signal identified by the given name to the given
1555
        value.
1556
1557
        >>> modbus set output register("output1",300,False)
1558
1559
        Parameters:
1560
        signal_name:          A string identifying an output register signal that in advance has been added.
1561
        register_value:       An integer which must be a valid word (0-65535) value.
1562
        is_secondary_program: A boolean for interal use only. Must be set to False.
1563
        '''
1564
        raise NotImplementedError('Function Not yet implemented')
1565
1566
    def modbus_set_output_signal(self, signal_name, digital_value, is_secondary_program):
1567
        '''
1568
        Sets the output digital signal identified by the given name to the given
1569
        value.
1570
1571
        >>> modbus set output signal("output2",True,False)
1572
1573
        Parameters:
1574
        signal_name:          A string identifying an output digital signal that in advance has been added.
1575
        digital_value:        A boolean to which value the signal will be set.
1576
        is_secondary_program: A boolean for interal use only. Must be set to False.
1577
        '''
1578
        raise NotImplementedError('Function Not yet implemented')
1579
1580
    def modbus_set_runstate_dependent_choice(self, signal_name, runstate_choice):
1581
        '''
1582
        Sets whether an output signal must preserve its state from a program,
1583
        or it must be set either high or low when a program is not running.
1584
1585
        >>> modbus set runstate dependent choice("output2",1)
1586
1587
        Parameters:
1588
        signal_name:     A string identifying an output digital signal that in advance has been added.
1589
        runstate_choice: An integer: 0 = preserve program state, 1 = set low when a program is not running, 2 = set high when a program is not running.
1590
        '''
1591
        raise NotImplementedError('Function Not yet implemented')
1592
1593
    def modbus_set_signal_update_frequency(self, signal_name, update_frequency):
1594
        '''
1595
        Sets the frequency with which the robot will send requests to the
1596
        Modbus controller to either read or write the signal value.
1597
1598
        >>> modbus set signal update frequency("output2",20)
1599
1600
        Parameters:
1601
        signal_name: A string identifying an output digital signal that in advance has been added.
1602
        update_frequency: An integer in the range 0-125 specifying the update frequency in Hz.
1603
        '''
1604
        raise NotImplementedError('Function Not yet implemented')
1605
1606
    def read_input_boolean_register(self, address):
1607
        '''
1608
        Reads the boolean from one of the input registers, which can also be
1609
        accessed by a Field bus. Note, uses it's own memory space.
1610
1611
        >>> bool val = read input boolean register(3)
1612
1613
        Parameters:
1614
        address: Address of the register (0:63)
1615
1616
        Return Value:
1617
        The boolean value held by the register (True, False)
1618
        '''
1619
        raise NotImplementedError('Function Not yet implemented')
1620
1621
    def read_input_float_register(self, address):
1622
        '''
1623
        Reads the float from one of the input registers, which can also be
1624
        accessed by a Field bus. Note, uses it's own memory space.
1625
1626
        >>> float val = read input float register(3)
1627
1628
        Parameters:
1629
        address: Address of the register (0:23)
1630
1631
        Return Value:
1632
        The value held by the register (float)
1633
        '''
1634
        raise NotImplementedError('Function Not yet implemented')
1635
1636
    def read_input_integer_register(self, address):
1637
        '''
1638
        Reads the integer from one of the input registers, which can also be
1639
        accessed by a Field bus. Note, uses it's own memory space.
1640
1641
        >>> int val = read input integer register(3)
1642
1643
        Parameters:
1644
        address: Address of the register (0:23)
1645
1646
        Return Value:
1647
        The value held by the register [-2,147,483,648 : 2,147,483,647]
1648
        '''
1649
        raise NotImplementedError('Function Not yet implemented')
1650
1651
    def read_output_boolean_register(self, address):
1652
        '''
1653
        Reads the boolean from one of the output registers, which can also be
1654
        accessed by a Field bus. Note, uses it's own memory space.
1655
1656
        >>> bool val = read output boolean register(3)
1657
1658
        Parameters:
1659
        address: Address of the register (0:63)
1660
1661
        Return Value:
1662
        The boolean value held by the register (True, False)
1663
        '''
1664
        raise NotImplementedError('Function Not yet implemented')
1665
1666
    def read_output_float_register(self, address):
1667
        '''
1668
        Reads the float from one of the output registers, which can also be
1669
        accessed by a Field bus. Note, uses it's own memory space.
1670
1671
        >>> float val = read output float register(3)
1672
1673
        Parameters:
1674
        address: Address of the register (0:23)
1675
1676
        Return Value:
1677
        The value held by the register (float)
1678
        '''
1679
        raise NotImplementedError('Function Not yet implemented')
1680
1681
    def read_output_integer_register(self, address):
1682
        '''
1683
        Reads the integer from one of the output registers, which can also be
1684
        accessed by a Field bus. Note, uses it's own memory space.
1685
1686
        >>> int val = read output integer register(3)
1687
1688
        Parameters:
1689
        address: Address of the register (0:23)
1690
1691
        Return Value:
1692
        The int value held by the register [-2,147,483,648 :
1693
        2,147,483,647]
1694
        '''
1695
        raise NotImplementedError('Function Not yet implemented')
1696
1697
    def read_port_bit(self, address):
1698
        '''
1699
        Reads one of the ports, which can also be accessed by Modbus clients
1700
1701
        >>> boolval = read port bit(3)
1702
1703
        Parameters:
1704
        address: Address of the port (See portmap on Support site,
1705
        page "UsingModbusServer" )
1706
1707
        Return Value:
1708
        The value held by the port (True, False)
1709
        '''
1710
        raise NotImplementedError('Function Not yet implemented')
1711
1712
    def read_port_register(self, address):
1713
        '''
1714
        Reads one of the ports, which can also be accessed by Modbus clients
1715
1716
        >>> intval = read port register(3)
1717
1718
        Parameters:
1719
        address: Address of the port (See portmap on Support site,
1720
        page "UsingModbusServer" )
1721
1722
        Return Value:
1723
        The signed integer value held by the port (-32768 : 32767)
1724
        '''
1725
        raise NotImplementedError('Function Not yet implemented')
1726
1727
    def rpc_factory(self, rpcType, url ):
1728
        '''
1729
        Creates a new Remote Procedure Call (RPC) handle. Please read the
1730
        subsection ef{Remote Procedure Call (RPC)} for a more detailed
1731
        description of RPCs.
1732
1733
        >>> proxy = rpc factory("xmlrpc", "http://127.0.0.1:8080/RPC2")
1734
1735
        Parameters
1736
        rpcType: The type of RPC backed to use. Currently only the "xmlrpc" protocol is available.
1737
1738
        url: The URL to the RPC server. Currently two protocols are
1739
        supported: pstream and http. The pstream URL looks
1740
        like "<ip-address>:<port>", for instance
1741
        "127.0.0.1:8080" to make a local connection on port
1742
        8080. A http URL generally looks like
1743
        "http://<ip-address>:<port>/<path>", whereby the
1744
        <path> depends on the setup of the http server. In
1745
        the example given above a connection to a local
1746
        Python webserver on port 8080 is made, which
1747
        expects XMLRPC calls to come in on the path
1748
        "RPC2".
1749
1750
        Return Value:
1751
        A RPC handle with a connection to the specified server using
1752
        the designated RPC backend. If the server is not available
1753
        the function and program will fail. Any function that is made
1754
        available on the server can be called using this instance. For
1755
        example "bool isTargetAvailable(int number, ...)" would be
1756
        "proxy.isTargetAvailable(var 1, ...)", whereby any number of
1757
        arguments are supported (denoted by the ...).
1758
        Note: Giving the RPC instance a good name makes programs much
1759
        more readable (i.e. "proxy" is not a very good name).
1760
        '''
1761
        raise NotImplementedError('Function Not yet implemented')
1762
1763
    def rtde_set_watchdog(self, variable_name, min_frequency, action='pause'):
1764
        '''
1765
        This function will activate a watchdog for a particular input variable to
1766
        the RTDE. When the watchdog did not receive an input update for the
1767
        specified variable in the time period specified by min frequency (Hz),
1768
        the corresponding action will be taken. All watchdogs are removed on
1769
        program stop.
1770
1771
        >>> rtde set watchdog("input int register 0", 10, "stop")
1772
1773
        Parameters:
1774
        variable name: Input variable name (string), as specified
1775
        by the RTDE interface
1776
        min frequency: The minimum frequency (float) an input
1777
        update is expected to arrive.
1778
        action: Optional: Either "ignore", "pause" or
1779
        "stop" the program on a violation of the
1780
        minimum frequency. The default action is
1781
        "pause".
1782
1783
        Return Value:
1784
        None
1785
        Note: Only one watchdog is necessary per RTDE input package to
1786
        guarantee the specified action on missing updates.
1787
        '''
1788
        raise NotImplementedError('Function Not yet implemented')
1789
1790
    def set_analog_inputrange(self, port, inputRange):
1791
        '''
1792
        Deprecated: Set range of analog inputs
1793
1794
        Port 0 and 1 is in the controller box, 2 and 3 is in the tool connector.
1795
1796
        Parameters:
1797
        port: analog input port number, 0,1 = controller, 2,3 = tool
1798
        inputRange: Controller analog input range 0: 0-5V (maps
1799
        automatically onto range 2) and range 2: 0-10V.
1800
        inputRange: Tool analog input range 0: 0-5V (maps
1801
        automatically onto range 1), 1: 0-10V and 2:
1802
        4-20mA.
1803
        Deprecated: The set standard analog input domain and
1804
        set tool analog input domain replace this function. Ports 2-3 should
1805
        be changed to 0-1 for the latter function. This function might be
1806
        removed in the next major release.
1807
        Note: For Controller inputs ranges 1: -5-5V and 3: -10-10V are no longer
1808
        supported and will show an exception in the GUI.
1809
        '''
1810
        raise NotImplementedError('Function Not yet implemented')
1811
1812
    def set_analog_outputdomain(self, port, domain):
1813
        '''
1814
        Set domain of analog outputs
1815
1816
        Parameters:
1817
        port: analog output port number
1818
        domain: analog output domain: 0: 4-20mA, 1: 0-10V
1819
        '''
1820
        raise NotImplementedError('Function Not yet implemented')
1821
1822
    def set_configurable_digital_out(self, n, b):
1823
        '''
1824
        Set configurable digital output signal level
1825
1826
        See also set standard digital out and set tool digital out.
1827
1828
        Parameters:
1829
        n: The number (id) of the output, integer: [0:7]
1830
        b: The signal level. (boolean)
1831
        '''
1832
        #self.robotConnector.RTDE.SetConfigurableDigitalOutput(n, b)
1833
        if b:
1834
            self.robotConnector.RTDE.setData('configurable_digital_output_mask', 2**n)
1835
            self.robotConnector.RTDE.setData('configurable_digital_output', 2**n)
1836
        else:
1837
            self.robotConnector.RTDE.setData('configurable_digital_output_mask', 2**n)
1838
            self.robotConnector.RTDE.setData('configurable_digital_output', 0)
1839
        self.robotConnector.RTDE.sendData()
1840
        self.robotConnector.RTDE.setData('configurable_digital_output_mask', 0)
1841
        self.robotConnector.RTDE.setData('configurable_digital_output', 0)
1842
1843
    def set_euromap_output(self, port_number, signal_value):
1844
        '''
1845
        Sets the value of a specific Euromap67 output signal. This means the
1846
        value that is sent from the robot to the injection moulding machine.
1847
        See http://universal-robots.com/support for signal specifications.
1848
1849
        >>> set euromap output(3,True)
1850
1851
        Parameters:
1852
        port number: An integer specifying one of the available
1853
        Euromap67 output signals.
1854
        signal value: A boolean, either True or False
1855
        '''
1856
        raise NotImplementedError('Function Not yet implemented')
1857
1858
    def set_euromap_runstate_dependent_choice(self, port_number, runstate_choice):
1859
        '''
1860
        Sets whether an Euromap67 output signal must preserve its state from a
1861
        program, or it must be set either high or low when a program is not
1862
        running. See http://universal-robots.com/support for signal
1863
        specifications.
1864
1865
        >>> set euromap runstate dependent choice(3,0)
1866
1867
        Parameters:
1868
        port number: An integer specifying a Euromap67
1869
        output signal.
1870
        runstate choice: An integer: 0 = preserve program state,
1871
        1 = set low when a program is not
1872
        running, 2 = set high when a program is
1873
        not running.
1874
        '''
1875
        raise NotImplementedError('Function Not yet implemented')
1876
1877
    def set_flag(self, n, b):
1878
        '''
1879
        Flags behave like internal digital outputs. The keep information
1880
        between program runs.
1881
1882
        Parameters:
1883
        n: The number (id) of the flag, integer: [0:32]
1884
        b: The stored bit. (boolean)
1885
        '''
1886
        raise NotImplementedError('Function Not yet implemented')
1887
1888
    def set_runstate_configurable_digital_output_to_value(self, outputId, state):
1889
        '''
1890
        Sets the output signal levels depending on the state of the program
1891
        (running or stopped).
1892
1893
        Example: Set configurable digital output 5 to high when program is not
1894
        running.
1895
1896
        >>> set runstate configurable digital output to value(5, 2)
1897
1898
        Parameters:
1899
        outputId: The output signal number (id), integer: [0:7]
1900
        state: The state of the output, integer: 0 = Preserve
1901
        state, 1 = Low when program is not running, 2 =
1902
        High when program is not running, 3 = High
1903
        when program is running and low when it is
1904
        stopped.
1905
        '''
1906
        raise NotImplementedError('Function Not yet implemented')
1907
1908
    def set_runstate_standard_analog_output_to_value(self, outputId, state):
1909
        '''
1910
        Sets the output signal levels depending on the state of the program
1911
        (running or stopped).
1912
1913
        Example: Set standard analog output 1 to high when program is not
1914
        running.
1915
1916
        >>> set runstate standard analog output to value(1, 2)
1917
1918
        Parameters:
1919
        outputId: The output signal number (id), integer: [0:1]
1920
        state: The state of the output, integer: 0 = Preserve
1921
        state, 1 = Min when program is not running, 2 =
1922
        Max when program is not running, 3 = Max when
1923
        program is running and Min when it is stopped.
1924
        '''
1925
        raise NotImplementedError('Function Not yet implemented')
1926
1927
    def set_runstate_standard_digital_output_to_value(self, outputId, state):
1928
        '''
1929
        Sets the output signal levels depending on the state of the program
1930
        (running or stopped).
1931
1932
        Example: Set standard digital output 5 to high when program is not
1933
        running.
1934
1935
        >>> set runstate standard digital output to value(5, 2)
1936
        Parameters
1937
        outputId: The output signal number (id), integer: [0:7]
1938
        state: The state of the output, integer: 0 = Preserve
1939
        state, 1 = Low when program is not running, 2 =
1940
        High when program is not running, 3 = High
1941
        when program is running and low when it is
1942
        stopped.
1943
        '''
1944
        raise NotImplementedError('Function Not yet implemented')
1945
1946
    def set_runstate_tool_digital_output_to_value(self, outputId, state):
1947
        '''
1948
        Sets the output signal levels depending on the state of the program
1949
        (running or stopped).
1950
1951
        Example: Set tool digital output 1 to high when program is not running.
1952
1953
        >>> set runstate tool digital output to value(1, 2)
1954
1955
        Parameters:
1956
        outputId: The output signal number (id), integer: [0:1]
1957
        state: The state of the output, integer: 0 = Preserve
1958
        state, 1 = Low when program is not running, 2 =
1959
        High when program is not running, 3 = High
1960
        when program is running and low when it is
1961
        stopped.
1962
        '''
1963
        raise NotImplementedError('Function Not yet implemented')
1964
1965
    def set_standard_analog_input_domain(self, port, domain):
1966
        '''
1967
        Set domain of standard analog inputs in the controller box
1968
1969
        For the tool inputs see set tool analog input domain.
1970
1971
        Parameters:
1972
        port: analog input port number: 0 or 1
1973
        domain: analog input domains: 0: 4-20mA, 1: 0-10V
1974
        '''
1975
        raise NotImplementedError('Function Not yet implemented')
1976
1977
    def set_standard_analog_out(self, n, f):
1978
        '''
1979
        Set standard analog output level
1980
        Parameters
1981
        n: The number (id) of the input, integer: [0:1]
1982
        f: The relative signal level [0;1] (float)
1983
        '''
1984
        raise NotImplementedError('Function Not yet implemented')
1985
1986
    def set_standard_digital_out(self, n, b):
1987
        '''
1988
        Set standard digital output signal level
1989
1990
        See also set configurable digital out and set tool digital out.
1991
1992
        Parameters:
1993
        n: The number (id) of the input, integer: [0:7]
1994
        b: The signal level. (boolean)
1995
        '''
1996
        #self.robotConnector.RTDE.SetStandardDigitalOutput(n, b)
1997
        if b:
1998
            self.robotConnector.RTDE.setData('standard_digital_output_mask', 2**n)
1999
            self.robotConnector.RTDE.setData('standard_digital_output', 2**n)
2000
        else:
2001
            self.robotConnector.RTDE.setData('standard_digital_output_mask', 2**n)
2002
            self.robotConnector.RTDE.setData('standard_digital_output', 0)
2003
        self.robotConnector.RTDE.sendData()
2004
        self.robotConnector.RTDE.setData('standard_digital_output_mask', 0)
2005
        self.robotConnector.RTDE.setData('standard_digital_output', 0)
2006
2007
2008
2009
    def set_tool_analog_input_domain(self, port, domain):
2010
        '''
2011
        Set domain of analog inputs in the tool
2012
2013
        For the controller box inputs see set standard analog input domain.
2014
2015
        Parameters:
2016
        port: analog input port number: 0 or 1
2017
        domain: analog input domains: 0: 4-20mA, 1: 0-10V
2018
        '''
2019
        raise NotImplementedError('Function Not yet implemented')
2020
2021
    def set_tool_digital_out(self, n, b):
2022
        '''
2023
        Set tool digital output signal level
2024
2025
        See also set configurable digital out and
2026
        set standard digital out.
2027
2028
        Parameters:
2029
        n: The number (id) of the output, integer: [0:1]
2030
        b: The signal level. (boolean)
2031
        '''
2032
        raise NotImplementedError('Function Not yet implemented')
2033
2034
    def set_tool_voltage(self, voltage):
2035
        '''
2036
        Sets the voltage level for the power supply that delivers power to the
2037
        connector plug in the tool flange of the robot. The votage can be 0, 12
2038
        or 24 volts.
2039
2040
        Parameters:
2041
        voltage: The voltage (as an integer) at the tool connector,
2042
        integer: 0, 12 or 24.
2043
        '''
2044
        raise NotImplementedError('Function Not yet implemented')
2045
2046
    def write_output_boolean_register(self, address, value):
2047
        '''
2048
        Writes the boolean value into one of the output registers, which can
2049
        also be accessed by a Field bus. Note, uses it's own memory space.
2050
2051
        >>> write output boolean register(3, True)
2052
2053
        Parameters:
2054
        address: Address of the register (0:63)
2055
        value: Value to set in the register (True, False)
2056
        '''
2057
2058
    def write_output_float_register(self, address, value):
2059
        '''
2060
        Writes the float value into one of the output registers, which can also
2061
        be accessed by a Field bus. Note, uses it's own memory space.
2062
2063
        >>> write output float register(3, 37.68)
2064
2065
        Parameters:
2066
        address: Address of the register (0:23)
2067
        value: Value to set in the register (float)
2068
        '''
2069
        raise NotImplementedError('Function Not yet implemented')
2070
2071
    def write_output_integer_register(self, address, value):
2072
        '''
2073
        Writes the integer value into one of the output registers, which can also
2074
        be accessed by a Field bus. Note, uses it's own memory space.
2075
2076
        >>> write output integer register(3, 12)
2077
2078
        Parameters:
2079
        address: Address of the register (0:23)
2080
        value: Value to set in the register [-2,147,483,648 :
2081
        2,147,483,647]
2082
        '''
2083
        raise NotImplementedError('Function Not yet implemented')
2084
2085
    def write_port_bit(self, address, value):
2086
        '''
2087
        Writes one of the ports, which can also be accessed by Modbus clients
2088
2089
        >>> write port bit(3,True)
2090
2091
        Parameters:
2092
        address: Address of the port (See portmap on Support site,
2093
        page "UsingModbusServer" )
2094
        value: Value to be set in the register (True, False)
2095
        '''
2096
        raise NotImplementedError('Function Not yet implemented')
2097
2098
    def write_port_register(self, address, value):
2099
        '''
2100
        Writes one of the ports, which can also be accessed by Modbus clients
2101
2102
        >>> write port register(3,100)
2103
2104
        Parameters:
2105
        address: Address of the port (See portmap on Support site,
2106
        page "UsingModbusServer" )
2107
        value: Value to be set in the port (0 : 65536) or (-32768 :
2108
        32767)
2109
        '''
2110
        raise NotImplementedError('Function Not yet implemented')
2111