Testing Gestalt
Making Fabnet
Following Getting Started With Gestalt Nodes, we successfully ran single node test.
It does not have to fuse or program the Gestalt nodes again.
Single gestalt node testing
And then testing with three nodes
Trying to identify each gestalt node.
But, the winter is coming again…
After this video, these three nodes cannot blink anymore….
In debug time, we found that the people from Fablab Leon faced same problem.
We tried to fuse and program these three Gestalt nodes with Arduino.
We were going to check the wires, but the programmer still cannot recognize
ATmega328P. So we removed the default crystal to burn them again.
It cannot work either.
However we have 4 Gestalt nodes and 3 of them cannot work, so we fused the rest
of workable one which can blink and identify by computer.
Boom! It worked!
Which means 3 of them might be totally broken with their ATmega328P.
While debugging, Kevin tried to write forward and reverse kinematics of hair milling
machine. Though it looks like delta machine, it’s not parallel mechanism at all. We
have to control the tool pointer and the position at the same time. So he modified the
Python code in machines.py and followed Delta Robot Kinematics by Steve Graves.
class kinematics(): # Bottom length = D # /\ A # / \ ^ x # / \ | # / \ | # / o \ o ---- > # / \ y # / \ # -------------- # C B #---Inherited from matrix class but not real matrix---- class deltaForwardTransform(matrix): '''Customized transform from axes input vector to delta hair-milling coordinate''' def __init__(self, L, r, rh, Lt, D): self.L = L #length of rod self.r = r #radius of iron ball self.rh = rh #diameter of your head self.Lt = Lt #length of tool-to-ball self.D = D #side length of bottom triangle self.Ax = math.sqrt(3)/3 * D self.Ay = 0 self.Bx = -math.sqrt(3)/6 * D self.By = 1/2 * D self.Cx = -math.sqrt(3)/6 * D self.Cy = -1/2 * D def transform(self, inputVector): if len(inputVector) != 3: #check to make sure that vectors match notice (self, 'vector length mismatch') return False Az = inputVector[0] Bz = inputVector[1] Cz = inputVector[2] P1 = numpy.array([self.Ax, self.Ay, Az]) P2 = numpy.array([self.Bx, self.By, Bz]) P3 = numpy.array([self.Cx, self.Cy, Cz]) ex = (P2 - P1)/(numpy.linalg.norm(P2 - P1)) i = numpy.dot(ex, P3 - P1) ey = (P3 - P1 - i*ex)/(numpy.linalg.norm(P3 - P1 - i*ex)) ez = numpy.cross(ex,ey) d = numpy.linalg.norm(P2 - P1) j = numpy.dot(ey, P3 - P1) xr = (pow((self.L+self.r),2) - pow((self.L+self.r),2) + pow(d,2))/(2*d) yr = ((pow((self.L+self.r),2) - pow((self.L+self.r),2) + pow(i,2) + pow(j, 2))/(2*j)) - ((i/j)*x) zr = numpy.sqrt(pow((self.L+self.r),2) - pow(x,2) - pow(y,2)) scale = self.rh / ( self.rh + self.Lt + self.r ) #scaling from iron ball to tool position x = scale * xr y = scale * yr z = scale * zr return [x,y] #---Inherited from matrix class but not real matrix---- class deltaReverseTransform(matrix): '''Customized transform from delta hair-milling coordinate to axes output vector''' def __init__(self, L, r, rh, Lt, D): self.L = L #length of rod self.r = r #radius of iron ball self.r = r #radius of iron ball self.rh = rh #radius of your head self.Lt = Lt #length of tool self.D = D #side length of bottom triangle self.Ax = math.sqrt(3)/3 * D self.Ay = 0 self.Bx = -math.sqrt(3)/6 * D self.By = 1/2 * D self.Cx = -math.sqrt(3)/6 * D self.Cy = -1/2 * D def transform(self, inputVector): # Only x,y allowed within inputVector if len(inputVector) != 2: #check to make sure that vectors match notice (self, 'vector length mismatch') return False x = inputVector[0] y = inputVector[1] z = math.sqrt(r**2 - x**2 - y**2) scale = ( self.rh + self.Lt + self.r ) / self.rh #scaling from tool position to iron ball position xr = scale * x yr = scale * y zr = scale * z Az = zr - math.sqrt( (self.L+self.r)**2 - (xr-self.Ax)**2 - (yrself. Ay)**2 ) Bz = zr - math.sqrt( (self.L+self.r)**2 - (xr-self.Bx)**2 - (yrself. By)**2 ) Cz = zr - math.sqrt( (self.L+self.r)**2 - (xr-self.Cx)**2 - (yrself. Cy)**2 ) return [Az, Bz, Cz] # Testing...... class hair_milling_delta(transform): def __init__(self, L, r, Lt, D): self.forwardMatrix = kinematics.deltaForwardTransform (L, r, rh, Lt, D) self.reverseMatrix = kinematics.deltaReverseTransform (L, r, rh, Lt, D)And added these to main file hair-milling.py
def initKinematics(self): self.xAxis = elements.elementChain.forward ([elements.microstep.forward(4), elements.stepper.forward(1.8), elements.leadscrew.forward(8), elements.invert.forward(True)]) self.yAxis = elements.elementChain.forward ([elements.microstep.forward(4), elements.stepper.forward(1.8), elements.leadscrew.forward(8), elements.invert.forward(False)]) self.zAxis = elements.elementChain.forward ([elements.microstep.forward(4), elements.stepper.forward(1.8), elements.leadscrew.forward(8), elements.invert.forward(False)]) self.stageKinematics = kinematics.hair_milling_delta()When he was all set, we found out the 3 of Gestalt nodes were definitely broken and cannot fuse.
You also can check out the files and design in our lab page.
List opportunities and improvements in the design for foot massage machine: