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