#!/usr/bin/env python3 # Copyright 2013 Jeff Epler # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. from vismach import * import hal import lineardeltakins import sys EFFECTOR_OFFSET = CARRIAGE_OFFSET = 30 MIN_JOINT = -375 MAX_JOINT = 0 for setting in sys.argv[1:]: exec(setting) c = hal.component("lineardelta") c.newpin("joint0", hal.HAL_FLOAT, hal.HAL_IN) c.newpin("joint1", hal.HAL_FLOAT, hal.HAL_IN) c.newpin("joint2", hal.HAL_FLOAT, hal.HAL_IN) c.newpin("joint3", hal.HAL_FLOAT, hal.HAL_IN) c.newpin("R", hal.HAL_FLOAT, hal.HAL_IN) c.newpin("L", hal.HAL_FLOAT, hal.HAL_IN) c['R'], c['L'] = lineardeltakins.get_geometry() c.ready() class DeltaTranslate(Collection): def __init__(self, parts, comp): self.comp = comp self.parts = parts self.x = self.y = self.z = 0 def apply(self): glPushMatrix() lineardeltakins.set_geometry(self.comp['R'], self.comp['L']) f = lineardeltakins.forward(self.comp['joint0'], self.comp['joint1'], self.comp['joint2']) if f is not None: self.x = x = f[0] self.y = y = f[1] self.z = z = f[2] else: x = self.x y = self.y z = self.z glTranslatef(x, y, z) def unapply(self): glPopMatrix() class TriangularPrismZ: def __init__(self, z0, z1, h): self.z0 = z0 self.z1 = z1 self.h = h def draw(self): x0 = 0 x1 = -self.h*sin(pi/3) x2 = self.h*sin(pi/3) y0 = self.h y1 = y2 = -self.h*cos(pi/3) z0 = self.z0 z1 = self.z1 glBegin(GL_TRIANGLES) glNormal3f(0, 0, 1) glVertex3f(x0, y0, z1) glVertex3f(x1, y1, z1) glVertex3f(x2, y2, z1) glNormal3f(0, 0, -1) glVertex3f(x2, y2, z0) glVertex3f(x1, y1, z0) glVertex3f(x0, y0, z0) glNormal3f(-cos(pi/3), sin(pi/3), 0) glVertex3f(x0, y0, z1) glVertex3f(x1, y1, z0) glVertex3f(x1, y1, z1) glVertex3f(x0, y0, z1) glVertex3f(x0, y0, z0) glVertex3f(x1, y1, z0) glNormal3f(0, -1, 0) glVertex3f(x1, y1, z1) glVertex3f(x2, y2, z0) glVertex3f(x2, y2, z1) glVertex3f(x1, y1, z1) glVertex3f(x1, y1, z0) glVertex3f(x2, y2, z0) glNormal3f(cos(pi/3), sin(pi/3), 0) glVertex3f(x2, y2, z1) glVertex3f(x0, y0, z0) glVertex3f(x0, y0, z1) glVertex3f(x2, y2, z1) glVertex3f(x2, y2, z0) glVertex3f(x0, y0, z0) glEnd() def build_joint(angle, joint): return Rotate([ Translate([ HalTranslate([ CylinderZ(MIN_JOINT, 5, MAX_JOINT, 5), HalTranslate([ Box(-CARRIAGE_OFFSET, -20, -20, 0, 20, 20) ], c, joint, 0, 0, 1) ], c, "R", 1, 0, 0) ], EFFECTOR_OFFSET + CARRIAGE_OFFSET, 0, 0) ], angle, 0, 0, 1) class Strut: def __init__(self, platform, angle, component, joint): self.platform = platform self.angle = radians(angle) self.component = component self.joint = joint self.q = gluNewQuadric() def draw(self): c = cos(self.angle) s = sin(self.angle) o = CARRIAGE_OFFSET oo = .4 * o x0 = self.platform.x + c*o sx = oo * -s y0 = self.platform.y + s*o sy = oo * c z0 = self.platform.z r2 = self.component['R'] + CARRIAGE_OFFSET x1 = r2 * cos(self.angle) y1 = r2 * sin(self.angle) z1 = self.component[self.joint] d = x1-x0, y1-y0, z1-z0 mag = sqrt(sum(di*di for di in d)) dx, dy, dz = (di/mag for di in d) L = self.component['L'] theta = atan2(dz, hypot(dx,dy)) phi = atan2(dy, dx) glPushMatrix() glTranslatef(x0+sx, y0+sy, z0) glRotatef(degrees(phi), 0, 0, 1) glRotatef(90-degrees(theta), 0, 1, 0) self.cylinder(L) glPopMatrix() glPushMatrix() glTranslatef(x0-sx, y0-sy, z0) glRotatef(degrees(phi), 0, 0, 1) glRotatef(90-degrees(theta), 0, 1, 0) self.cylinder(L) glPopMatrix() def cylinder(self, L): gluCylinder(self.q, 5, 5, L, 32, 1) # bottom cap glRotatef(180,1,0,0) gluDisk(self.q, 0, 5, 32, 1) glRotatef(180,1,0,0) # the top cap needs flipped and translated glTranslatef(0,0, L) gluDisk(self.q, 0, 5, 32, 1) tooltip = Capture() tool = DeltaTranslate([ Translate([ Color((.5,.5,.5,0), [ Translate([tooltip], 0,0,-40), Rotate([TriangularPrismZ(0, 5, EFFECTOR_OFFSET*2)], 180, 0, 0, 1), CylinderZ(-40, 0, -30, 10), CylinderZ(-30, 10, 10, 10) ]) ], 0, 0, -5)], c) red = (1,.5,.5,0) green = (.5,1,.5,0) blue = (.5,.5,1,0) joint0 = Color(red, [build_joint(90, "joint0")]) joint1 = Color(green, [build_joint(210, "joint1")]) joint2 = Color(blue, [build_joint(330, "joint2")]) work = Capture() strut0 = Color(red, [Strut(tool, 90, c, "joint0")]) strut1 = Color(green, [Strut(tool, 210, c, "joint1")]) strut2 = Color(blue, [Strut(tool, 330, c, "joint2")]) table = CylinderZ(MIN_JOINT-5, 300, MIN_JOINT, 300) model = Collection([table, joint0, joint1, joint2, tool, strut0, strut1, strut2, work]) main(model, tooltip, work, 1500)