14
14
from roboticstoolbox .backends .Connector import Connector
15
15
# from roboticstoolbox.robot.DHLink import DHLink
16
16
# from roboticstoolbox.robot.Robot import Robot as r
17
- from roboticstoolbox import DHLink , DHRobot
17
+ # from roboticstoolbox.robot import DHLink, DHRobot
18
+
19
+ # from roboticstoolbox.robot.DHRobot import DHRobot
20
+ # from roboticstoolbox.robot.DHLink import DHLink
18
21
19
22
GraphicsCanvas3D = None
20
23
GraphicsCanvas2D = None
@@ -79,7 +82,7 @@ class VPython(Connector): # pragma nocover
79
82
# TODO be able to add ellipsoids (vellipse, fellipse)
80
83
# TODO be able add lines (for end-effector paths)
81
84
82
- def __init__ (self ):
85
+ def __init__ (self , ** kwargs ):
83
86
"""
84
87
Open a localhost session with no canvases
85
88
@@ -98,12 +101,12 @@ def __init__(self):
98
101
self ._recording_fps = None
99
102
self ._thread_lock = threading .Lock ()
100
103
104
+ self .launch_options = kwargs # save launch options
105
+
101
106
self ._create_empty_session ()
102
107
103
108
def launch (
104
- self , is_3d = True , height = 500 , width = 888 ,
105
- title = '' , caption = '' , grid = True ,
106
- g_col = None ):
109
+ self , ** kwargs ):
107
110
"""
108
111
Launch a graphical backend in a browser tab
109
112
@@ -112,6 +115,16 @@ def launch(
112
115
113
116
"""
114
117
118
+ # merge instantiation & launch options
119
+ args = {** self .launch_options , ** kwargs }
120
+ is_3d = args .get ('is_3d' , True )
121
+ height = args .get ('height' , 500 )
122
+ width = args .get ('width' , 888 )
123
+ title = args .get ('title' , 'Robotics Toolbox for Python: VPython display' )
124
+ caption = args .get ('caption' , '' )
125
+ grid = args .get ('grid' , False )
126
+ g_col = args .get ('g_col' , None )
127
+
115
128
super ().launch ()
116
129
117
130
self .canvas_settings .append (
@@ -127,11 +140,11 @@ def launch(
127
140
GraphicsCanvas2D (height , width , title , caption ,
128
141
grid , g_col ))
129
142
130
- def step (self , id , q = None , fig_num = 0 ):
143
+ def step (self , dt = None , id = None , q = None , fig_num = 0 ):
131
144
"""
132
145
Update the graphical scene
133
146
134
- :param id: The Identification of the robot to remove . Can be either the
147
+ :param id: The Identification of the robot to move . Can be either the
135
148
DHRobot or GraphicalRobot
136
149
:type id: :class:`~roboticstoolbox.robot.DHRobot.DHRobot`,
137
150
:class:`roboticstoolbox.backends.VPython.graphics_robot.GraphicalRobot`
@@ -166,32 +179,40 @@ def step(self, id, q=None, fig_num=0):
166
179
raise ValueError (
167
180
"Figure number must be between 0 and total number of canvases" )
168
181
169
- # If DHRobot given
170
- if isinstance (id , DHRobot ):
171
- robot = None
172
- # Find first occurrence of it that is in the correct canvas
173
- for i in range (len (self .robots )):
174
- if self .robots [i ].robot is id and \
175
- self .canvases [fig_num ].is_robot_in_canvas (
176
- self .robots [i ]):
177
- robot = self .robots [i ]
178
- break
182
+ # If GraphicalRobot given
183
+ if isinstance (id , GraphicalRobot ):
184
+ if self .canvases [fig_num ].is_robot_in (id ):
185
+ poses = id .fkine (q )
186
+ id .set_joint_poses (poses )
187
+
188
+ #if isinstance(id, DHRobot): # HACK avoid circular import
189
+ else :
190
+ # robot = None
191
+ # # Find first occurrence of it that is in the correct canvas
192
+ # for i in range(len(self.robots)):
193
+ # if self.robots[i].robot is id and \
194
+ # self.canvases[fig_num].is_robot_in_canvas(
195
+ # self.robots[i]):
196
+ # robot = self.robots[i]
197
+ # break
198
+ if id is None :
199
+ robot = self .robots [0 ]
179
200
if robot is None :
180
201
print ("No robot" )
181
202
return
182
203
else :
183
204
poses = robot .fkine (q )
184
205
robot .set_joint_poses (poses )
185
206
# ElseIf GraphicalRobot given
186
- elif isinstance ( id , GraphicalRobot ):
187
- if self . canvases [ fig_num ]. is_robot_in ( id ):
188
- poses = id . fkine ( q )
189
- id . set_joint_poses ( poses )
190
- # Else
191
- else :
192
- raise TypeError (
193
- "Input must be a Robot (or subclass) or "
194
- "GraphicalRobot, given {0}" . format ( type ( id )) )
207
+
208
+ # # Else
209
+ # else:
210
+ # raise TypeError(
211
+ # "Input must be a Robot (or subclass) or "
212
+ # "GraphicalRobot, given {0}".format(type(id)))
213
+
214
+ if dt is not None :
215
+ sleep ( dt )
195
216
196
217
def reset (self ):
197
218
"""
@@ -265,16 +286,16 @@ def close(self):
265
286
266
287
self .canvases = []
267
288
268
- def add (self , fig_num , name , dhrobot ):
289
+ def add (self , dhrobot , fig_num = 0 , name = None ):
269
290
"""
270
291
Add a robot to the graphical scene
271
292
293
+ :param dhrobot: The ``DHRobot`` object (if applicable)
294
+ :type dhrobot: class:`~roboticstoolbox.robot.DHRobot.DHRobot`, None
272
295
:param fig_num: The canvas number to place the robot in
273
296
:type fig_num: int
274
297
:param name: The name of the robot
275
298
:type name: `str`
276
- :param dhrobot: The ``DHRobot`` object (if applicable)
277
- :type dhrobot: class:`~roboticstoolbox.robot.DHRobot.DHRobot`, None
278
299
:raises ValueError: Figure number must be between 0 and number of
279
300
figures created
280
301
:return: object id within visualizer
@@ -306,6 +327,9 @@ def add(self, fig_num, name, dhrobot):
306
327
307
328
super ().add ()
308
329
330
+ if name is None :
331
+ name = dhrobot .name
332
+
309
333
# Sanity check input
310
334
if fig_num < 0 or fig_num > len (self .canvases ) - 1 :
311
335
raise ValueError (
0 commit comments