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