/ docs / src / gui / vismach.txt
vismach.txt
  1  [[cha:vismach]]
  2  
  3  = Vismach
  4  
  5  Vismach is a set of Python functions that can be used to create and animate
  6  models of machines. Vismach displays the model in a 3D viewport and the model
  7  parts are animated as the values of associated HAL pins change.
  8  
  9  image::images/vismach.png[align="center", alt="Vismach displays the model in a 3D viewport"]
 10  
 11  The Vismach viewport view can be manipulated as follows
 12  
 13  * zoom  by scroll wheel or right button drag
 14  
 15  * pan by left button drag
 16  
 17  * rotate by middle-button drag or shift-drag.
 18  
 19  A Vismach model takes the form of a Python script and can use standard Python
 20  syntax. This means that there is more than one way to lay out the script, but
 21  in the examples given in this document I will use the simplest and most basic
 22  of them.
 23  
 24  The basic sequence in creating the Vismach model is
 25  
 26  * Create the HAL pins that control the motion
 27  
 28  * Create the parts
 29  
 30  * Define how they move
 31  
 32  * Assemble into movement groups
 33  
 34  == Start the script
 35  
 36  It is useful for testing to include the '#!/usr/bin/env python' to allow the file
 37  to be run as a script. The first thing to do is to import the required
 38  libraries.
 39  
 40  ----
 41  #!/usr/bin/env python
 42  
 43  from vismach import *
 44  import hal
 45  import math
 46  import sys
 47  ----
 48  
 49  == Create the HAL pins.
 50  
 51  Hal pins are created with the normal Python "hal" library, and are not
 52  specific to Vismach. Further details can be found in the <<cha:halmodule,
 53  Creating Userpace Components in Python>> section.
 54  A component should be created with a name that matches the script file name and
 55  then the HAL pins are added to that component. They will be referenced by their
 56  component handle and short name when used to animate the Vismach model.
 57  
 58   c = hal.component("samplegui")
 59   c.newpin("joint0", hal.HAL_FLOAT, hal.HAL_IN)
 60   c.newpin("joint1", hal.HAL_FLOAT, hal.HAL_IN)
 61   c.ready()
 62  
 63  Will create HAL pins 'samplegui.joint0' and 'samplegui.joint1'. When loading
 64  the Vismach model with 'loadusr -W samplegui' the 'c.ready()' function tells
 65  loadusr it's ready.
 66  
 67  == Creating Parts
 68  
 69  It is probably easiest to create geometry in a CAD package and import into
 70  the model script with the AsciiSTL() or AsciiOBJ() functions.
 71  Both functions can take one of two named arguments, either a filename or raw
 72  data
 73  
 74   part = AsciiSTL(filename="path/to/file.stl)
 75   part = AsciiSTL(data="solid part1 facet normal ....")
 76   part = AsciiOBJ(filename="path/to/file.obj)
 77   part = AsciiOBJ(data="v 0.123 0.234 0.345 1.0 ...")
 78  
 79  The parts will be created in the Vismach space in the same locations as they
 80  occupy in the STL or OBJ space. This means that it may be possible to assemble
 81  the model in the CAD package.
 82  
 83  Alternatively parts can be created inside the model script from a range of
 84  shape primitives. Many shapes are created at the origin and need to be moved to
 85  the required location after creation.
 86  
 87   cylinder = CylinderX(x1, r1, x2, r2)
 88   cylinder = CylinderY(y1, r1, y2, r2)
 89   cylinder = CylinderZ(z1, r1, z2, r2)
 90  
 91  Creates a (optionally tapered) cylinder on the given axis with the given radii
 92  at the given points on the axis.
 93  
 94   sphere = Sphere(x, y, z, r)
 95  
 96  Creates a sphere of radius r at (x,y,z)
 97  
 98   triangle = TriangleXY(x1, y1, x2, y2, x3, y3, z1, z2)
 99   triangle = TriangleXZ(x1, z1, x2, z2, x3, z3, y1, y2)
100   triangle = TriangleYZ(y1, z1, y2, z2, y3, z3, x1, x2)
101  
102  Creates a triangular plate between planes defined by the last two values
103  parallel to the specified plane, with vertices given by the three coordinate
104  pairs.
105  
106   arc = ArcX(x1, x2, r1, r2, a1, a2)
107  
108  Create an arc shape.
109  
110   box = Box(x1, y1, z1, x2, y2, z2)
111  
112  Creates a rectangular prism with opposite corners at the specified positions
113  and edges parallel to the XYZ axes.
114  
115   box = BoxCentered(xw, yw, zw)
116  
117  Creates an xw by yw by zw box centred on the origin.
118  
119   box = BoxCenteredXY(xw, yw, z)
120  
121  Creates a box of width xw / yw and height z.
122  
123  Composite parts may be created by assembling these primitives either at creation
124  time or subsequently:
125  
126   part1 = Collection([Sphere(100,100,100,50), CylinderX(100,40,150,30)])
127   part2 = Box(50,40,75,100,75,100)
128   part3 = Collection([part2, TriangleXY(10,10,20,10,15,20,100,101)])
129   part4 = Collection([part1, part2])
130  
131  == Moving Parts
132  
133  Parts may need to be moved in the Vismach space to assemble the model. They may
134  also need to be moved to create the animation as the animation rotation axis is
135  created at the origin (but moves with the Part).
136  
137   part1 = Translate([part1], x, y, z)
138  
139  Move part1 the specified distances in x, y and z.
140  
141   part1 = Rotate([part1], theta, x, y, z)
142  
143  Rotate the part by angle theta about an axis between the origin and x, y, z.
144  
145  == Animating Parts
146  
147  To animate the model (controlled by the values of HAL pins) there are two
148  functions 'HalTranslate' and 'HalRotate'. For parts to move inside an assembly
149  they need to have their HAL motions defined before being assembled with the
150  "Collection" command. The rotation axis and and translation vector move with the
151  part as it is moved by the vismach script during model assembly, or as it moves
152  in response to the HAL pins as the model is animated.
153  
154   part = HalTranslate([part], comp, "hal_pin", xs, ys, zs)
155  
156  The function arguments are first a collection/part which can be pre-created
157  earlier in the script, or could be created at this point if preferred eg
158  part1 = HalTranslate([Box(....)], ...).
159  The the HAL component is the next argument, ie the object returned by the comp
160  = hal.component(...) command. After that is the name of the HAL in that will
161  animate the motion, this needs to match an existing HAL pin that is part of
162  the HAL component created earlier in the script.
163  
164  Then follow the X, Y, Z scales. For a Cartesian machine created at 1:1 scale
165  this would typically be 1,0,0 for a motion in the positive X direction. However
166  if the STL file happened to be in cm and the machine was in inches, this
167  could be fixed at this point by using 0.3937 (1cm /2.54in) as the scale.
168  
169   part = HalRotate([part], comp, "hal_pin", angle_scale, x, y, z)
170  
171  This command is similar in its operation to HalTranslate except that it is
172  typically necessary to move the part to the origin first to define the axis.
173  The axis of rotation is from the origin point to the point defined by (x,y,z).
174  Rotation angles are in degrees, so for a rotary joint with a 0-1 scaling you
175  would need to use an angle scale of 360. When the part is moved back away from
176  the origin to its correct location the axis of rotation can be considered to
177  remain "embedded" in the part.
178  
179  == Assembling the model.
180  
181  In order for parts to move together they need to be assembled with the
182  Collection() command. It is important to assemble the parts and define their
183  motions in the correct sequence. For example to create a moving head milling
184  machine with a rotating spindle and an animated draw bar you would:
185  
186  * Create the head main body.
187  
188  * Create the spindle at the origin.
189  
190  * Define the rotation.
191  
192  * Move the head to the spindle or spindle to the head.
193  
194  * Create the draw bar
195  
196  * Define the motion of the draw bar
197  
198  * Assemble the three parts into a head assembly
199  
200  * Define the motion of the head assembly.
201  
202  In this example the spindle rotation is indicated by rotation of a set of drive
203  dogs:
204  
205  ----
206  #Drive dogs
207  dogs = Box(-6,-3,94,6,3,100)
208  dogs = Color([1,1,1,1],[dogs])
209  dogs = HalRotate([dogs],c,"spindle",360,0,0,1)
210  dogs = Translate([dogs],-1,49,0)
211  
212  #Drawbar
213  draw = CylinderZ(120,3,125,3)
214  draw = Color([1,0,.5,1],[draw])
215  draw = Translate([draw],-1,49,0)
216  draw = HalTranslate([draw],c,"drawbar",0,0,1)
217  
218  # head/spindle
219  head = AsciiSTL(filename="./head.stl")
220  head = Color([0.3,0.3,0.3,1],[head])
221  head = Translate([head],0,0,4)
222  head = Collection([head, tool, dogs, draw])
223  head = HalTranslate([head],c,"Z",0,0,0.1)
224  
225  # base
226  base = AsciiSTL(filename="./base.stl")
227  base = Color([0.5,0.5,0.5,1],[base]) 
228  # mount head on it
229  base = Collection([head, base])
230  ----
231  
232  Finally a single collection of all the machine parts, floor and work (if any)
233  needs to be created. For a serial machine each new part will be added to the
234  collection of the previous part. For a parallel machine there may be several
235  "base" parts. Thus, for example, in scaragui.py link3 is added to link2, link2
236  to link1 and link1 to link0, so the final model is created by
237  
238   model = Collection([link0, floor, table])
239  
240  Whereas a VMC model with separate parts moving on the base might have
241  
242   model = Collection([base, saddle, head, carousel])
243  
244  == Other functions
245  
246   part = Color([colorspec], [part])
247  
248  Sets the display color of the part. Note that unlike the other functions the
249  part definition comes second in this case. The colorspec consists of the three
250  RGB values and an opacity. For example [1,0,0,0.5] for a 50% opacity red.
251  
252   myhud = Hud()
253  
254  Creates a heads-up display in the Vismach GUI to display such items as axis
255  positions. 
256  
257  ////
258  Need to play around with this to see how it works.
259  ////
260  
261   part = Capture()
262  
263  I have no idea what this does, but it seems to be important for tool tip
264  visualization.
265  
266   main(model, tooltip, work, size=10, hud=0, rotation_vectors=None, lat=0, lon=0)
267  
268  This is the command that makes it all happen, creates the display etc.
269  "model" should be a collection that contains all the machine parts. "tooltip"
270  and "work" need to be created by Capture() to visualize their motion in the
271  back plot. See scaragui.py for an example of how to connect the tool tip to a tool
272  and the tool to the model.
273  
274  Either rotation_vectors or latitude / longitude can be used to set the
275  original viewpoint and it is advisable to do as the default initial viewpoint
276  is rather unhelpfully from immediately overhead.
277  
278  size sets the extent of the volume visualized in the initial view.
279  hud refers to a head-up display of axis positions.
280  
281  == Basic structure of a Vismach script.
282  
283  ----
284  #imports
285  from vismach import *
286  import hal
287  #create the HAL component and pins
288  comp = hal.component("compname")
289  comp.newpin("pin_name", hal.HAL_FLOAT, hal.HAL_IN)
290  ...
291  #create the floor, tool and work
292  floor = Box(-50, -50, -3, 50, 50, 0)
293  work = Capture()
294  tooltip = Capture()
295  ...
296  #Build and assemble the model
297  part1 = Collection([Box(-6,-3,94,6,3,100)])
298  part1 = Color([1,1,1,1],[part1])
299  part1 = HalRotate([part1],comp,"pin_name",360,0,0,1)
300  part1 = Translate([dogs],-1,49,0)
301  ...
302  #create a top-level model
303  model = Collection([base, saddle, head, carousel])
304  #Start the visualization
305  main(model, tooltip, work, 100, lat=-75, lon=215)
306  ----