INSTRUCTING MACHINES Workshop_2 Tutors: Shajay Bhooshan, Alicia Nahmad Vazquez, Vishu Bhooshan, Dave Reeves Albert Yen, Federico Borello, Fernando Alvarenga, Philipp Siedler
INSTRUCTING MACHINES _04 _06 _34 _34 _46 _58 _70 _80 _92
Introduction 1_ Computer Instruction C++ Code 2_ Catalogue Behavior Types 2.1_ Particles to Target 2.2_ Particles to Particles 2.3_ Particles to Environment
3_ Robotic Arm End Effector Design 4_ Robot Instruction and Analysis Drawing Conclusion
Introduction
WORKFLOW
Workshop Introduction This digital workshop is called instructing machines and aimed to teach C++, with predifined framework and libraries also known as Level 2 C-Programming, in a close relation to the real world, instructing a six axis robot. More generally speaking, instructing a machine with a computer language as the medium.
generative code
global variables
A behaviour driven, generative code had to be written, drawing points and lines onto a digital planar canvas. This simple geometric elements had to be compiled to a machine readable code, a G-Code, to be executed by the NACHI MZ07 6 Axis Robot. The only constraints for the drawing of points and lines were the robots motion abilities, its mounting position and the given physical operating canvas with the size of an A3 landscape. Both, the digital and the robotic work could be treated individually, as long as the output of the digital world were points on the XYPlane written as (x,y,z), to be compiled and interpolated by the NACHI Software to a G-Code. Between the actual point output of the code and the NACHI compiler software of the teams choice could be used as possible manipulator. Since natural systems are highly generative, a logic and appealing consequence for this project was to analyze a system in the physical world, translate and describe it in the digital world in form of a code and feed it back to the physical world with a 6 Axis robot and its customized end effector as tool of expression.
model
view
controller
target force
particles + targets
randomize particles
gravity force
randomize targets
spin force
switch charge targets
particle to particle force
switch charge p to p
drag force
magnetic force
cells class
“chemical deposition� force
export .eps
Adobe Illustrator
export g-code .txt
Rhinoceros
grid cells
Grasshopper
Nachi compiler
Nachi Robot
4
5
C++ served as the main coding language in this project. As frame work the Zaha Hadid CODE group under Shajay Bhooshan provided the team with various libraries to include for example a 3D space as canvas and the nachi robot. The general partisions of the generative code we wrote are Model including: “General Variables”, “Setup” and “Update”, View including: “Draw” and Controller including: “Key Press”, “Mouse Press” and “Mouse Motion”. The generative code is divided into three elements: 1. Particles, 2. Targets and 3. Forces manipulating the particles position.
1_ Computer Instruction C++ Code
In the “Model” partition the 3D workspace, the “Targets”, “Particles” and “Forces” are initialized. The targets are setup by fixed locations and charges, particles are randomly spread into a defined frame. The force field is created by a set of forces which are differenciated in their behaviour: 1. Forces which act from the global environment onto the particles: Gravity Force, Spin Force, Drag Force. 2. Forces acting between particles and targets: Target Force, Cell Center “Chemical Deposition” Force. 3. Forces inbetween particles: Particle to Particle Force. The “Update” partition updates the position of the particles, their color coding, their possible trail and the color coding of the cell where the particles “deposit chemicals”. Under “Draw”, particles, particle trails, targets and colored cells are initialized to be visualized. “View” visualizes the generative process of particle movement and the “Controller” partition enables the user to: reverse the charge of the targets, reverse attraction to repulsion force between the particles, reset the setup, switch to the top view, reset and reorganize targets and export an .eps vector files.
7
1_ Computer Instruction C++ Code #include “main.h” // include “main” class #include “Cells.h” // include “Cells” class #include “gl2ps.h” // include “gl2ps” (.eps export) class
int frm = 0;
// initial integer for frame (frm) counter
bool run = false;
// initial boolean value to run code
string seq = “Sequence: “; // sequence label of keypress sequence /// --- --- --- /// GLOBAL VARIABLES /// --- --- --- /// #define Res 200 // setting up resolution of canvas #define MaxTrail 1 // trail length of particles #define MaxParticles 100 // particle count #define MaxTargets 1 // target count float unitX = 200/Res; // cell size x float unitY = 200/Res; // cell size y float dirLength; // --float cellsColor[Res*Res]; // one dimensional array for cells color float charges[MaxTargets]; // target charge float AttRep = -1; // attraction/repulsion multiplicator value (particle to particle) float dist[MaxTargets]; float min, max; // min and max value for color remap of “chemical deposition” in cells
vec gravity(0, 0, -1); // direction gravity vector vec chemicalForce[MaxParticles][Res*Res]; // two dimensional array for “chemical deposition” of particles in cells vec dir[MaxTargets]; // one dimensional array of vec target[MaxTargets]; // one dimensional array of target position point vectors vec pos[MaxParticles]; // one dimensional array of particle position point vectors vec vel[MaxParticles]; // one dimensional array of velocity vectors vec forces[MaxParticles]; // one dimensional array of applied forces vector array vec trail[MaxParticles][MaxTrail]; // two dimensional array of particles and their trail position point vectors vec chemF[MaxParticles]; // one dimensional array of particle to cell with “chemical deposition” vectors vec cellCenterPt[Res * Res]; // cell center position point vectors Cells mycells[Res*Res]; // one dimensional array for cells SliderGroup S; // slider function
double timeStep = 0.01; // time step size double targetStrength = 0.2; // target attraction/repulsion strength (target to particle/particle to target) double gravityStrength = 0.0; // gravity strength (environment to particle) double spinStrength = 0.0; // spin strength (environment to particle) double dragStrength = 0.1; // drag strength (environment to particle) double collisonStrength = 0.5; // particle attraction/repulsion strength (particle to particle) double collisonRadius = 10; // particle attraction/repulsion radius (particle to particle) double magneticStrength = 0.1; // target magnetic force (target to particle) double chemicalStrength = 0.1; // cell center point attraction strength (particle to cell “chemical deposition”)
8
9
p0 +c2
1_ Computer Instruction C++ Code ButtonGroup B;
// button function
p2
/// PARTICLE - TARGET - MAGNETIC FORCES
/// --- --- --- /// MODEL /// --- --- --- /// /// PARTICLE - PARTICLE TO PARTICLE FORCES vec PtoP(int particleId1, int particleId2) // particle to particle vector { float distance = pos[particleId1].distanceTo(pos[particleId2]); // distance between particles vec dir = pos[particleId2] - pos[particleId1]; // direction vectors from particle to particle vec collisionForce(0, 0, 0); // reset collisionForce vector if (distance < collisonRadius) // checking distance between particles to be affected by collision force { collisionForce = dir * AttRep; // calculation of collision force vector collisionForce.normalise(); // normalizing collision force vector } return collisionForce; // output collision force }
t3
d3 d1
t1
p1
p3
d2
1/d2
p0
/// GRAVITY FORCE
p
p0 t3
/// SPIN FORCE
d3
d1 void applySpinForce() // target tspin force function t1 1 { for (int i = 0; i < MaxParticles;d1i++) // loop through particles d2 p0 { p for (int j = 0; j < MaxTargets; j++) p // loop through targets t2 { float distance = pos[i].distanceTo(target[j]); // distances between particles and targets vec dir = target[j] - pos[i]; // direction vectors from particles to targets g dir.normalise(); // normalize direction vetors vec UpVec(0, 0, 1); // --0
t3
d3 d1 d2
10
t2
+c2
t2 p2
void applyGravity() // environment gravity force vector function { for (int i = 0; i < MaxParticles; i++) // loop through particles { forces[i] += gravity * gravityStrength; // integrating gravity force into global field of forces } }
3
2
d
p0
+c1
void applyMagneticForce() // target magnetic force function { p1 for (int i = 0; i < MaxParticles; i++) // loop through particles p3 p0 +c1 -c3 { 2 1/d d for (int j = 0; j < tMaxTargets; j++) // loop through targetsp 1/d2 0 3 { p0 p0 distance = pos[i].distanceTo(target[j]); d3 float // distances between particles and targets +c2 vec dir = target[j] - pos[i]; // direction vectors from particles to targets d1 dir.normalise(); // normalizetdirection vetors 1 p2 vec f = (dir * magneticStrength * charges[j]) / ((distance + 0.01) * (distance + 0.01)); // calculating magnetic force vector f.normalise(); // normalize magnetig force vector d2 // integrating magnetic force into global field of forces forces[i] += f * 0.1; -c } 1/d } }
g t1
t2
p0 t
v
t1
t1 p0
p
d1
p0
d1
11 g
v
1_ Computer Instruction C++ Code
p vec spinDir = dir.cross(UpVec);
d1
p0
// -- forces[i] += spinDirp* spinStrength; // integrating spin force into global field of forces 1 } p3 +c1 } g } d 1/d2 p0
-c3 1/d
2
p0
/// DRAG FORCE void applyDragForce() // particle drag force function { for (int i = 0; i < MaxParticles; i++) // loop through p2 particles { vec dragDir = vel[i] * -1; // direction vectors from particles to targets forces[i] += dragDir * dragStrength; // integrating drag force into global field of forces } } /// PARTICLE - ENVIRONMENT - “CHEMICAL DEPOSITION” FORCE
+c2
p0
v
p0 void cellAttForce() // cell center point attraction function { t3 for (int i = 0; i < MaxParticles; i++) // loop through particles d3 { d1 deposition” chemF[i] = vec(0,0,0); // “chemical force array t1 int currentI = pos[i].x; // particle position x int currentj = pos[i].y; // particle position y for (int u = currentI - unitX; u < currentI + d 2*unitX; u+=unitX) // loop through neighbouring cell in x direction of particle 2 { for (int z = currentj - unitY; z < currentj + 2*unitY; z+=unitY) // loop through neighbouring cell in y direction of particle
12
t2
{ int dx; // initializing x int dy; // initializing y dx = floor(u / unitX); // x position in cell grid dy = floor(z / unitY); // y position in cell grid int id = dx * Res + dy; // index in one dimensional array of cells if (id >= 0 && id < Res * Res) // if condition to make sure index != outside of array { cellCenterPt[id] = mycells[id].p + vec(unitX / 2, unitY / 2, 0); // cell center vector vec nVec = cellCenterPt[id] - pos[i]; // attraction vector particle to cell center nVec.normalise(); // normalise particel to cell center vector chemF[i] += nVec; // vector addition of particel to cell center vector chemF[i].normalise(); // normalise resulting vector } else continue; // if index larger than array count continue } } forces[i] += chemF[i] * chemicalStrength; // integrating “chemical deposition” force into global field of forces } } /// INTEGRATE FORCES void integrateForces() // integrating forces { for (int i = 0; i < MaxParticles; i++) { vec acc = forces[i] / 1; // acceleration = force / mass vec newVel = vel[i] + acc * timeStep; // new velocity = old velocity + acceleration * timestep vec newPos = pos[i] + newVel * timeStep; // new position = old position + new velocity * timestep
13
1_ Computer Instruction C++ Code pos[i] = newPos; // update particle position vel[i] = newVel; // update velocity value } } /// UPDATE FUNCTION void updateFunction() // update { // deposit chemical for (int i = 0; i < MaxParticles; i++) // loop through neighbouring cell in y direction of particle { int dx; // initializing x int dy; // initializing y dx = floor(pos[i].x / unitX); // x position in cell grid dy = floor(pos[i].y / unitY); // y position in cell grid int id = dx * Res + dy; // index in one dimensional array of cells if (id >= 0 && id < Res * Res) // if condition to make sure index != outside of array { mycells[id].chemicalA += 10; // add value to “chemical deposition” array } } // find min max of chemical A ; min = 100000000; // initializing min max = -1 * min; // initializing max for (int i = 0; i < Res * Res; i++) // loop through cell array { min = MIN(mycells[i].chemicalA, min); // calculating min value of “chemical deposition” max = MAX(mycells[i].chemicalA, max); // calculating max value of “chemical deposition”
14
} // reset forces for (int i = 0; i < MaxParticles; i++) // loop through particles { forces[i] = vec(0, 0, 0); // reset forces } // calculate particle to particle forces for (int i = 0; i < MaxParticles; i++) // loop through particles { for (int j = i + 1; j < MaxParticles; j++) // loop through particles { if (i == j) continue; vec PtoPForce = PtoP(i, j); // initialising particle to particle vector force forces[i] += PtoPForce * collisonStrength; // integrating particle to particle force into global field of forces forces[j] += PtoPForce * collisonStrength * -1; // integrating particle to particle force into global field of forces } } // target force for (int i = 0; i < MaxParticles; i++) // loop through particles { float leastD = -100000; // initialize lowest number int idofTargets; // initialize target index int idofParticles = i; // initialize particle index for (int j = 0; j < MaxTargets; j++) // loop through targets { float dist = pos[i].distanceTo(target[j]); // distance between particle and target if (dist > leastD) // if statement to sort distances to largest and smallest value {
15
1_ Computer Instruction C++ Code leastD = dist; // replace distance idofTargets = j; // relate to target index } } vec p = pos[idofParticles]; // particle position vector vec dir = target[idofTargets] - p; // particle to target vector dir.normalise(); // normalise particle to target vector float dirLength = dir.mag(); // magnitude value of particle to target vector if (dirLength < 10) // if condition to calculate closest particle to target { forces[i] += dir * targetStrength; // integrating target force into global field of forces } else continue; } //applyGravity(); // call apply gravity function cellAttForce(); // call apply â&#x20AC;&#x153;chemical depositionâ&#x20AC;? force function applyDragForce(); // call apply drag force function applySpinForce(); // call apply spin force function applyMagneticForce(); // call apply magnetic force function integrateForces(); // call intergrate forces function // update trail for (int i = 0; i < MaxParticles; i++) // loop through particles { trail[i][0] = pos[i]; // put the current position of particle into first place of myTrail array for (int j = MaxTrail - 1; j >= 1; j--) { trail[i][j] = trail[i][j - 1]; // shift the other elements in the array } } frm++; // update frames }
16
/// SETUP void setup() { backGround(0.75,0.75,0.75,0); // background color // initialise points/particles & velocity for (int i = 0; i < MaxParticles; i++) // loop through particles { vel[i] = vec(0, 0, 0); // reset velocity vector pos[i] = vec(ofRandom(75, 125), ofRandom(75, 125), 0); // random position of particles } for (int i = 0; i < MaxTargets; i++) // loop through targets { target[0] = vec(100, 100, 0); // target 0 position target[1] = vec(150, 50, 0); // target 1 position target[2] = vec(50, 50, 0); // target 2 position target[3] = vec(150, 150, 0); // target 3 position target[4] = vec(50, 150, 0); // target 4 position } for (int i = 0; i < MaxTargets; i++) // loop through targets { charges[0] = -1; // target 0 charge charges[1] = 1; // target 1 charge charges[2] = -1; // target 2 charge charges[3] = -1; // target 3 charge charges[4] = +1; // target 4 charge } // creating cell grid for (int i = 0; i < Res; i++) // loop through first dimension of cell array Res
17
1_ Computer Instruction C++ Code { for (int j = 0; j < Res; j++) // loop through second dimension of cell array Res { int id = i * Res + j; // index of Res array mycells[id].p = vec(unitX*i, unitY*j, 0); // position of lower left corner of cell in grid array mycells[id].unitX = unitX; // first dimension of array mycells[id].unitY = unitY; // second dimension of array mycells[id].chemicalA = 0.0; // reset “chemical deposition” force } } // slider and button on canvas S = *new SliderGroup(); // call slider function B = *new ButtonGroup(vec(50, 500, 0)); // call button function
B.addButton(&run, “run”); // run button
S.addSlider(&timeStep, “timeStep”); // slider 0 S.sliders[0].minVal = 0.01; // slider 0 min value S.sliders[0].maxVal = 1.00; // slider 0 max value
S.addSlider(&gravityStrength, “gravityStrength”); // slider 1 S.sliders[1].minVal = 0.00; // slider 1 min value S.sliders[1].maxVal = 10.00; // slider 1 max value
S.addSlider(&targetStrength, “targetStrength”); // slider 2 S.sliders[2].minVal = 0.00; // slider 2 min value S.sliders[2].maxVal = 10.00; // slider 2 max value
S.addSlider(&spinStrength, “spinStrength”); // slider 3 S.sliders[3].minVal = 0.00; // slider 3 min value
18
S.sliders[3].maxVal = 1.00; // slider 3 max value
S.addSlider(&dragStrength, “dragStrength”); // slider 4 S.sliders[4].minVal = 0.00; // slider 4 min value S.sliders[4].maxVal = 10.00; // slider 4 max value
S.addSlider(&collisonStrength, “collisonStrength”); S.sliders[5].minVal = 0.00; // slider 5 min value S.sliders[5].maxVal = 10.00; // slider 5 max value
S.addSlider(&collisonRadius, “collisonRadius”); // slider 6 S.sliders[6].minVal = 0.01; // slider 6 min value S.sliders[6].maxVal = 100.00; // slider 6 max value
S.addSlider(&magneticStrength, “magneticStrength”); S.sliders[7].minVal = 0.01; // slider 7 min value S.sliders[7].maxVal = 10.00; // slider 7 max value
// slider 7
S.addSlider(&chemicalStrength, “chemicalStrength”); S.sliders[8].minVal = 0.00; // slider 8 min value S.sliders[8].maxVal = 10.00; // slider 8 max value
// slider 8
// slider 5
} /// UPDATE void update(int value) // call update function { if (run)updateFunction(); }
19
1_ Computer Instruction C++ Code
/// --- --- --- /// VIEW /// --- --- --- /// void draw() // draw { glEnable(GL_POINT_SMOOTH); S.draw(); // - B.draw(); // --
// --
// draw particles for (int i = 0; i < MaxParticles; i++) // loop through particles { glPointSize(1); // particle size 1 vec4 color = getColour(i, 0, MaxParticles); // particle color mapping glColor3f(255,255,255); // particle color drawPoint(pos[i]); // draw particle point } // draw targets glColor3f(1, 0, 0); // target color for (int i = 0; i < MaxTargets; i++) // loop through targets { drawPoint(target[i]); // draw target point } // draw particle trail for (int i = 0; i < MaxParticles; i++) // loop through particles { int end = frm % MaxTrail; // frame per trail size if (MaxTrail < frm) end = MaxTrail;
20
int trailNum = MaxTrail; for (int j = 0; j < end-1; j++) // loop through trail related to time (frame) { float val = ofMap(i, 0, MaxParticles, 0, 1); // map particles to 0 to 1 value float valTrail = ofMap(j, 0, end, 0, 255); // map trails to 0 to 255 value glColor4f(0, val, valTrail, valTrail); // trail color glPointSize(0.3); // trail point size 0.3 //drawPoint(trail[i][j]); //drawLine(trail[i][j], trail[i][j + 1]); } } // draw grid cell for (int j = 0; j < Res * Res; j++) // loop through one dimensional cell array { glPointSize(5); // point size 5 vec4 clr = getColour(mycells[j].chemicalA, min,max); // cell color map related to â&#x20AC;&#x153;chemical depositionâ&#x20AC;? value glColor3f(clr.r,clr.g,0); // cell color drawRectangle(mycells[j].p, mycells[j].p + vec(unitX, unitY, 0)); // draw rectangle as cell }
// setup2d(); glColor3f(0, 0, 0); drawString(seq, 50, 600); restore3d();
}
21
1_ Computer Instruction C++ Code /// --- --- --- /// CONTROLLER /// --- --- --- /// /// CONTROLLER - KEY PRESS void keyPress(unsigned char k, int xm, int ym) // key press function { if (k == ‘t’) { seq += “t”; // if “t” is pressed add to sequence label on canvas } if (k == ‘v’) { seq += “v”; // if “v” is pressed add to sequence label on canvas for (int i = 0; i < MaxTargets; i++) // loop through targets { charges[i] *= -1; // switch charge of targets } } if (k == ‘c’) { seq += “c”; AttRep *= -1; } if (k == ‘s’) { setup(); }
22
// if “c” is pressed add to sequence label on canvas // switch from attraction to repulsion of particle to particle force
// reset setup
if (k == ‘t’) { topCamera(); }
// switch to top view
if (k == ‘w’) { for (int i = 0; i < MaxTargets; i++) // loop through targets { target[i] = vec(ofRandom(-100, 100), ofRandom(-100, 100), 0); } }
// randomize target
if (k == ‘A’) // to print high res EPS image { FILE *fp; // initialize file function int state = GL2PS_OVERFLOW, buffsize = 0; // prevent overflow fp = fopen(“out.eps”, “w”); printf(“Writing ‘out.eps’... “); while (state == GL2PS_OVERFLOW) { buffsize += winW * winH; gl2psBeginPage(“test”, “gl2psTestSimple”, NULL, GL2PS_EPS, GL2PS_SIMPLE_SORT, GL2PS_USE_CURRENT_VIEWPORT, GL_RGBA, 0, NULL, 0, 0, 0, buffsize, fp, “out.eps”); draw(); state = gl2psEndPage(); } fclose(fp); printf(“Done!\n”); }
23
1_ Computer Instruction C++ Code if (k == ‘u’) { updateFunction(); // update function by step } } /// CONTROLLER - MOUSE PRESS void mousePress(int b, int s, int x, int y) { if (GLUT_LEFT_BUTTON == b && GLUT_DOWN == s) { S.performSelection(x, y, HUDSelectOn); B.performSelection(x, y); } } /// CONTROLLER - MOUSE MOTION void mouseMotion(int x, int y) { S.performSelection(x, y, HUDSelectOn); }
#ifndef CELLS #define CELLS #include “main.h” class Cells { public: // to make it accessable from everywhere in the code // global variables vec p; // initializing vector p float unitX; // size x of cell float unitY; // size y of cell float chemicalA; // “chemical deposition” value Cells() // constructor { p = vec(0,0,0); // vector p unitX = 1; // size x of cell unitY = 1; // size y of cell chemicalA = 0; // “chemical deposition” value }; Cells(vec _p, float _unitX, float _unitY, float _chemicalA) { p = _p; unitX = _unitX; unitY = _unitY; chemicalA = _chemicalA; }
// overload constructor
}; #endif
24
25
1_ Computer Instruction C++ Code #include “main.h” #include “ALICE_ROBOT_DLL.h” using namespace ROBOTICS;
// import robot library // set robot library namespace to ROBOTICS
/// --- --- --- /// GLOBAL VARIABLES /// --- --- --- /// #define Z 21.79
// define Z value from robot working plate
Robot_Symmetric nachi; // initialize Robot_Symmetric class with nachi istance SliderGroup S; // initialize SliderGroup class with S istance ButtonGroup B; // initialize ButtonGroup class with B istance importer ptsReader; // initialize importer class with ptsReader istance string mesh_names[5] = { “data/link0.obj”, “data/link1.obj”, “data/link2.obj”, “data/link3.obj”, “data/link4.obj” }; ofstream myfile, myfile_write; // initialize ofstream class with myfile and myfile_write instances int ptcnt = 0; // point counter bool computeAO = false; char gcode[600];
// boolean type set to false
// array of characters to store the GCODE data
vec target(10, 0, 0); // vector position for target vec diff; // vector difference /// --- --- --- /// MODEL /// --- --- --- /// /// SETUP void setup() { vec pt = nachi.ForwardKineMatics(nachi.inv_rot); // setup forward kinematics calculation nachi.addMeshes(); // import robot meshes
26
//initialize string class with mesh_names istance
S = *new SliderGroup(); // declare new slider group // sliders connected to joints rotation S.addSlider(&nachi.rot[0], “J1”); // slider J1 S.addSlider(&nachi.rot[1], “J2”); // slider J2 S.addSlider(&nachi.rot[2], “J3”); // slider J3 S.addSlider(&nachi.rot[3], “J4”); // slider J4 S.addSlider(&nachi.rot[4], “J5”); // slider J5 S.addSlider(&nachi.rot[5], “J6”); // slider J6 // sliders connected to joints rotation S.sliders[0].attachToVariable(&nachi.rot[0], -170, 170); S.sliders[1].attachToVariable(&nachi.rot[1], -45, 170); S.sliders[2].attachToVariable(&nachi.rot[2], -67, 120); S.sliders[3].attachToVariable(&nachi.rot[3], -190, 190); S.sliders[4].attachToVariable(&nachi.rot[4], -120, 120); S.sliders[5].attachToVariable(&nachi.rot[5], -370, 370);
// slider 0 // slider 1 // slider 2 // slider 3 // slider 4 // slider 5
nachi.rot[1] = 90; // set J2 rotation to 90 degrees target = vec(nachi.joints[5].x, nachi.joints[5].y, nachi.joints[5].z); // set position of joints coordinates ptsReader = *new importer(“data/1/White.txt”, 10000, 1.0); // imports points coordinates ptsReader.readPts_p5(); // read points } /// UPDATE void update(int value) { vec pt = nachi.ForwardKineMatics(nachi.rot); // update forward kinematics calculation }
27
1_ Computer Instruction C++ Code /// --- --- --- /// VIEW /// --- --- --- ///
drawString(s, winW * 0.5, 50);
void draw() { backGround(0.75); // set background color drawGrid(20.0); // draw grid 20x20
glColor3f(0, 0, 1); sprintf_s(s, “ TCP_Z %1.4f %1.4f %1.4f”, nachi.TCP_z.x, nachi.TCP_z.y, nachi.TCP_z.z); drawString(s, winW * 0.5, 75);
S.draw(); // display slider S group B.draw(); // display slider B group nachi.draw(true); // display nachi robot glColor3f(1, 0, 1); // set color drawCircle(target, 5, 32); // draw circle in target vector posistion glPointSize(3); // set point size glColor3f(0, 0, 1); // set color for (int i = 0; i < ptsReader.nCnt; i++) drawPoint(ptsReader.nodes[i].pos); // display imported points drawLine(nachi.joints[5], nachi.joints[5] - diff); // display line from J6 to vector position diff // display joints rotation values char s[200]; double l = 0.; for (int i = 1; i < DOF; i++) l += nachi.joints[i].distanceTo(nachi.joints[i - 1]); sprintf_s(s, “ link lengths %1.4f”, l); setup2d(); drawString(s, winW - 250, winH - 50); glColor3f(1, 0, 0); sprintf_s(s, “ TCP_X %1.4f %1.4f %1.4f”, nachi.TCP_x.x, nachi.TCP_x.y, nachi.TCP_x.z); drawString(s, winW * 0.5, 25); glColor3f(0, 1, 0); sprintf_s(s, “ TCP_Y %1.4f %1.4f %1.4f”, nachi.TCP_y.x, nachi.TCP_y.y, nachi.TCP_y.z);
28
vec pp = nachi.joints[5] + vec(0, 0, -24.98); sprintf_s(s, “ %1.4f %1.4f %1.4f”, pp.x, pp.y, pp.z); drawString(s, winW * 0.5, 125); drawString(gcode, winW * 0.5, 100); restore3d(); }
// restore 3d view
/// --- --- --- /// CONTROLLER /// --- --- --- /// void keyPress(unsigned char k, int xm, int ym) { if (k == ‘r’) { nachi.inv_rot.setConstant(0.); // set rotation constant to 0 degrees nachi.inv_rot(1) = 90.0; // set rotation to 90 degrees for (int i = 0; i < DOF; i++)nachi.rot[i] = nachi.inv_rot(i); } if (k == ‘n’) { target = ptsReader.nodes[ptcnt].pos; // assign points imported as target for the robot to check reachability target.z += Z; // lift the Z value of the target of the value defined in the global variables #define federico #ifdef federico vec diff1 = vec(-9.21906, 12.4999, 221.047);
// define vector diff1
29
1_ Computer Instruction C++ Code vec diff0 = vec(0, 0, 0); // define vector diff0 diff = (diff1 - diff0); // vector subtraction between diff1 - diff0 to get the vector distance float d = diff.mag(); // conversion from vector to float diff = diff.normalise() * d * 0.1; // define increment of movement target = ptsReader.nodes[ptcnt].pos + diff; // movement of the robot to target points vec x1 = vec(46.1273, 12.7838, 123.621); vec x0 = vec(45.642, 11.9514, 123.353); vec y1 = vec(46.3664, 11.3972, 123.763); // calculation of the vector distances to get the orientation of the TCP vec z1 = vec(45.1524, 11.9563, 124.225); vec x = (x1 - x0).normalise(); vec z = (z1 - x0).normalise() * -1; vec y = z.cross(x).normalise(); // cross product between vectors to get the perpendicular x.normalise(); y.normalise(); z.normalise(); #endif
// normalize the vectors to unit vectors
#ifndef federico vec x(1, 0, 0); vec y(0, 1, 0); vec z(0, 0, -1); #endif //#ifndef federico // vec x(1, 0, 0); // vec y(0, 1, 0); // set TCP orientation to straight // vec z(0, 0, -1); //#endif nachi.TCP_x = x; nachi.TCP_y = y; // assign X,Y,Z vectors to the TCP vector positions nachi.TCP_z = z; nachi.inverseKinematics_analytical(target, false); // calculate inverse kinematics
30
ptcnt++; if (ptcnt >= ptsReader.nCnt)ptcnt = 0; // reset point counter if greater the number of points imported } if (k == ‘N’) { myfile_write.open(“data/Nachi Files/1/MZ07-01-A.050”, ios::out); // open a new text file if (myfile_write.fail())cout << “ error in opening file “ << “MZ07-01-A.083” << endl; // check if the file has been correctly opened for (int i = 0; i < ptsReader.nCnt; i++) { cout << target.z << endl; // close the text file target = ptsReader.nodes[i].pos; target.z += Z; #ifdef federico vec diff1 = vec(-9.21906, 12.4999, 221.047); vec diff0 = vec(0, 0, 0); diff = (diff1 - diff0); float d = diff.mag(); diff = diff.normalise() * d * 0.1; target = ptsReader.nodes[i].pos + diff; vec x1 = vec(46.1273, 12.7838, 123.621); vec x0 = vec(45.642, 11.9514, 123.353); vec y1 = vec(46.3664, 11.3972, 123.763); vec z1 = vec(45.1524, 11.9563, 124.225); vec x = (x1 - x0).normalise(); vec z = (z1 - x0).normalise() * -1; // x = z.cross(vec(1, 0, 0)).cross(z).normalise(); vec y = z.cross(x).normalise(); x.normalise();
31
1_ Computer Instruction C++ Code y.normalise(); z.normalise(); #endif
} } myfile_write.close(); } if (k == ‘=’)target.x += 1.1; if (k == ‘-’)target.x -= 1.1; if (k == ‘0’)target.y += 1.1; if (k == ‘9’)target.y -= 1.1; // move the target position manually along X,Y,Z if (k == ‘7’)target.z += 1.1; if (k == ‘8’)target.z -= 1.1; if (k == ‘ ‘)computeAO = !computeAO; if (k == ‘c’)myfile.close(); }
#ifndef federico vec x(1, 0, 0); vec y(0, 1, 0); vec z(0, 0, -1); #endif //#ifndef federico //vec x(1,0,0); //vec y(0,1,0); //vec z(0, 0, -1); //#endif nachi.TCP_x = x; //vec(1, 0, 0); nachi.TCP_y = y;// vec(0, 1, 0); nachi.TCP_z = z;// vec(0, 0, -1);
void mousePress(int b, int state, int x, int y) { if (GLUT_LEFT_BUTTON == b && GLUT_DOWN == state) { S.performSelection(x, y, HUDSelectOn); // move S sliders along X and Y B.performSelection(x, y); // move B slider along X and Y } }
nachi.inverseKinematics_analytical(target, false); vec pt = nachi.ForwardKineMatics(nachi.rot); { float e_x, e_y, e_z, r, p, y; e_x = nachi.rot[0]; e_y = nachi.rot[1]; e_z = nachi.rot[2]; r = 0; // set a fixed angle to joint J4 p = nachi.rot[4]; y = 270; // set a fixed angle to joint J6; sprintf_s(gcode, “MOVEX A=6,AC=0,SM=0,M1J,P,( %1.2f,%1.2f,%1.2f,%1.2f,%1.2f,%1.2f),T=0.1,H=3,MS, CONF=0001”, e_x, e_y, e_z, r, p, y); write a text file with the GCODE informations myfile_write << gcode << endl; // close the text file
32
void mouseMotion(int x, int y) { S.performSelection(x, y, HUDSelectOn); }
// make the S sliders selectable
//
33
2_ Catalogue Behavior Types 2.1_ Particles to Target
2_ Catalogue Behavior Types SETUP
SETUP
Particles 1000
Target Strength
0.00
Spin Strength
0.00
Drag Strength
0.20
Collision Strength
0.50 2.00
0.00
36
Particles 1000
Gravity Strength
0.00
0.00
Targets 8 Time Step
0.50
0.10
Trails 500
Magnetic Strength Chemical Radius Chemical Strength
Gravity Strength
0.00
Target Strength
0.00
Spin Strength
0.00
Drag Strength
0.20
Collision Strength
0.50 2.00 0.10 0.00 0.00
Targets 8 Time Step
0.50
Collision Radius
Trails 500
Collision Radius Magnetic Strength Chemical Radius Chemical Strength
37
2_ Catalogue Behavior Types SETUP Particles 1000
SETUP Trails 500
Particles 1000 Time Step
0.20
Gravity Strength
0.00
Target Strength
0.20
Spin Strength
0.00
Drag Strength
0.10
Collision Strength
0.50
Magnetic Strength
0.10 5.0 0.50
Chemical Radius Chemical Strength
Trails 500 0.50
Spin Strength
0.00
Drag Strength
0.20
Collision Strength
0.50 2.00
0.00 0.00
Time Step
Target Strength
0.00
0.10
Targets 8
Gravity Strength
0.00
Collision Radius
1.00
38
Targets 8
Collision Radius Magnetic Strength Chemical Radius Chemical Strength
39
2_ Catalogue Behavior Types SETUP
SETUP
Particles 1000
Target Strength
0.00
Spin Strength
0.00
Drag Strength
0.20
Collision Strength
0.50 2.00
0.00
40
Particles 1000
Gravity Strength
0.00
0.00
Targets 8 Time Step
0.50
0.10
Trails 500
Magnetic Strength Chemical Radius Chemical Strength
Gravity Strength
0.00
Target Strength
0.00
Spin Strength
0.00
Drag Strength
0.20
Collision Strength
0.50 2.00 0.10 0.00 0.00
Targets 8 Time Step
0.50
Collision Radius
Trails 500
Collision Radius Magnetic Strength Chemical Radius Chemical Strength
41
2_ Catalogue Behavior Types SETUP
SETUP
Particles 1000
Target Strength
0.00
Spin Strength
0.00
Drag Strength
0.20
Collision Strength
0.00 2.00
0.00
42
Particles 1000
Gravity Strength
0.00
0.00
Targets 8 Time Step
0.50
0.10
Trails 500
Magnetic Strength Chemical Radius Chemical Strength
Gravity Strength
0.00
Target Strength
0.00
Spin Strength
0.00
Drag Strength
0.20
Collision Strength
0.50 2.00 0.10 0.00 0.00
Targets 8 Time Step
0.50
Collision Radius
Trails 500
Collision Radius Magnetic Strength Chemical Radius Chemical Strength
43
2_ Catalogue Behavior Types SETUP Particles 1000
SETUP Trails 500
Targets 8 Time Step
1.00
Gravity Strength
0.00
Target Strength
0.20
Spin Strength
0.00
Drag Strength
0.80
Collision Radius
0.10 7.00
5.00
Chemical Strength
Targets 8 Time Step Gravity Strength
0.00
Target Strength
0.20
Spin Strength
0.00
Drag Strength
0.80
Collision Strength
1.50
Collision Radius
0.10
Magnetic Strength Chemical Radius
0.50
Trails 500
1.00
Collision Strength
1.50
44
Particles 1000
7.00
Magnetic Strength Chemical Radius
0.50 5.00
Chemical Strength
45
2_ Catalogue Behavior Types 2.2_ Particle to Particle
2_ Catalogue Behavior Types
SETUP Particles 1000
SETUP Trails 500
Targets 8
Particles 1000 Time Step
0.20
Gravity Strength
0.00
Target Strength
0.20
Spin Strength
0.00
Drag Strength
0.10
Collision Strength
0.50
Magnetic Strength Chemical Radius
0.50 5.00
48
Chemical Strength
Gravity Strength
0.00
Target Strength
0.20
Spin Strength
0.00
Drag Strength
0.10
Collision Strength
0.50
Collision Radius
Targets 8 Time Step
0.20
10.00 0.10
Trails 500
5.00
Collision Radius Magnetic Strength
0.10
Chemical Radius
0.50 5.00
Chemical Strength
49
2_ Catalogue Behavior Types
SETUP
SETUP
Particles 1000
Target Strength
0.10
Spin Strength
0.00
Drag Strength
0.10
Collision Strength
0.50 3.00
0.50
50
Particles 1000
Gravity Strength
0.00
0.00
Targets 8 Time Step
0.20
0.10
Trails 500
Chemical Radius Chemical Strength
Targets 8 Time Step
0.20
Gravity Strength
0.00
Target Strength
0.20
Spin Strength
0.00
Drag Strength
0.10
Collision Strength
0.50
Collision Radius Magnetic Strength
Trails 500
Collision Radius
2.00
Magnetic Strength
0.10
Chemical Radius
0.50 5.00
Chemical Strength
51
2_ Catalogue Behavior Types
SETUP Particles 1000
SETUP Trails 500
Targets 8 Time Step
0.20
Gravity Strength
0.00
Target Strength
0.20
Spin Strength
0.00
Drag Strength
0.10
Collision Strength
0.50 9.00
Chemical Radius
0.50 5.00
Trails 500
Chemical Strength
Targets 8 Time Step
0.20
Gravity Strength
0.00
Target Strength
0.20
Spin Strength
0.00
Drag Strength
0.10
Collision Strength
0.50
Collision Radius Magnetic Strength
0.10
52
Particles 1000
6.00
Collision Radius Magnetic Strength
0.10
Chemical Radius
0.50 5.00
Chemical Strength
53
2_ Catalogue Behavior Types
SETUP Particles 1000
Trails 500
SETUP
Targets 8 Time Step
0.20
Gravity Strength
0.00
Target Strength
0.20 0.00 0.10
Drag Strength
0.050
4.00
Gravity Strength Target Strength Spin Strength Drag Strength
0.10
Collision Strength
0.50 6.00
Magnetic Strength
0.10
Chemical Radius
0.50 5.00
Chemical Strength
Collision Radius Magnetic Strength
0.10
Chemical Radius
0.50 5.00
54
Targets 8 Time Step
0.00 0.20
Collision Radius
Trails 500
0.20
Spin Strength
Collision Strength
0.50
Particles 1000
Chemical Strength
55
2_ Catalogue Behavior Types SETUP Particles 1000
Trails 500
SETUP Particles 1000
Trails 500
Time Step
0.20
Gravity Strength
0.00
Target Strength
0.20 0.10 0.10
4.00 0.10 0.50 5.00
56
Drag Strength
0.20
Chemical Radius
Spin Strength
0.00 0.10
Magnetic Strength
Target Strength
0.20
Spin Strength
Collision Radius
Gravity Strength
0.00
Drag Strength Collision Strength Collision Radius
4.00
Collision Strength
0.70
Time Step
0.20
Targets 8
Targets 8
Magnetic Strength
0.10
Chemical Radius
0.50 5.00
Chemical Strength
Chemical Strength
57
2_ Catalogue Behavior Types 2.3_ Particles to Environment
2_ Catalogue Behavior Types
SETUP
SETUP Particles 1000
Trails 500
Time Step
0.20
Gravity Strength
0.00
Target Strength
0.20
Spin Strength
0.00
Drag Strength
0.10
Collision Strength
0.50
Magnetic Strength
0.10
5.00
Chemical Strength
Targets 8 Time Step Gravity Strength
0.00
Target Strength
0.20
Spin Strength
0.00
Drag Strength
0.10
Collision Strength
0.50
Collision Radius
1.00
Magnetic Strength
0.10
Chemical Radius
0.50
Trails 500
0.20
Collision Radius
1.00
60
Particles 1000
Targets 8
10.00 0.50
Chemical Radius Chemical Strength
61
2_ Catalogue Behavior Types
SETUP
SETUP Particles 1000
Trails 500
Time Step
0.20 0.00 0.20 0.00 0.10
Target Strength
0.00
Spin Strength
0.00
Drag Strength
0.00
Magnetic Strength
0.10 19.90
62
0.00
Time Step Gravity Strength Target Strength Spin Strength Drag Strength Collision Strength Collision Radius
5.0095
Magnetic Strength
0.10 10.00
Chemical Radius Chemical Strength
Targets 8
0.50
Collision Radius
1.00
Trails 500
0.20
Gravity Strength
Collision Strength
0.50
0.50
Particles 1000
Targets 8
0.50
Chemical Radius Chemical Strength
63
2_ Catalogue Behavior Types
SETUP Particles 1000
SETUP Trails 500
Gravity Strength
0.00
Target Strength
0.20
Spin Strength
0.00
Drag Strength
0.10
Collision Strength
0.50
Magnetic Strength
0.10 5.00
Targets 8 Time Step Gravity Strength
0.00
Target Strength
0.00
Spin Strength
0.00
Drag Strength
0.00
Collision Strength
0.50
Collision Radius
2.0098
Magnetic Strength
0.10
Chemical Radius Chemical Strength
Trails 500
0.20
Collision Radius
0.5091
64
Particles 1000 Time Step
0.20
0.50
Targets 8
10.00 0.50
Chemical Radius Chemical Strength
65
2_ Catalogue Behavior Types
SETUP Particles 1000
SETUP Trails 500
Targets 8 Time Step
0.20
Gravity Strength
0.00
Spin Strength
0.00
Drag Strength
0.10
Collision Strength
0.50 10.00
5.00
66
Gravity Strength
0.00
Target Strength
5.00
Spin Strength
0.00
Drag Strength
0.10
Collision Strength
0.50 10.00
5.00 0.50
Collision Radius Magnetic Strength
0.10
Chemical Radius Chemical Strength
Targets 8 Time Step
Collision Radius Magnetic Strength
0.10
Trails 500
0.20
Target Strength
0.20
0.50
Particles 1000
Chemical Radius Chemical Strength
67
2_ Catalogue Behavior Types
SETUP Particles 1000
SETUP Trails 500
Targets 8 Time Step
0.010
Gravity Strength
0.00
Target Strength
0.50
Spin Strength
0.0250
Drag Strength
0.80
Collision Strength
0.50 10.00 6.1539 0.00 0.0100
68
Particles 1000 0.0100 0.00 0.50 0.10 0.10 0.50
Collision Radius Magnetic Strength Chemical Radius Chemical Strength
Trails 500
Targets 8 Time Step Gravity Strength Target Strength Spin Strength Drag Strength Collision Strength Collision Radius
10.00 0.10 0.00 0.0100
Magnetic Strength Chemical Radius Chemical Strength
69
3_ Robotic Arm End Effector Design
70
NACHI FUJIKOSHI spans a wide range of manufacturing fields. These include products for the machining industry, such as tools, machine tools and ultra-precision machines, as well as robotic systems for automating production lines and reducing power consumption. We are using the Nachi MZ07 robotic arm, itself is an ultra highspeed motion capability with advanced through-arm dress capabilities to simplify routing of hoses and cables for material handling. In this workshop we will be designing custom pen effector to attached at the end of the robotic arm agent.
71
3_ Robotic Arm End Effector Design
Top View
This custom 3d printed end effector is design to hold four UNI POSCA marker individually, three medium size, one large size. Inside the bottom of pen holder, is design to store magnetic sphere to attach with markers, for convince replacing different type of colors.
Bottom view
1.5 mm
1.5 mm
Orthogonal
Perspective
Perspective Front view
72
Dots Lines Colors 1.3 mm and 1.5 mm
Bottom view
Top view
Front view
1.5 mm
1.5 mm
Fabrication Method: 3D Print Material: PLA 2.75 mm Fabrication Time: 8 hours Machine: Ultimaker 2
Front view
Orthogonal
73
3_ Robotic Arm End Effector Design G3 NACHI MZ07
NACHI MZ07
Agent A Agent A
Agent B
G2 Agent B
Effector Bolt
Effector
Bolt
G4
G1
G5 G0 Top View
Perspective
Front view
Side view
After 3d printed custom effector, the effector attached to the agent that is connect between Nachi robotic arm and effector with four bolt on the side.
74
75
3_ Robotic Arm End Effector Design
NACHI MZ07 Working Envelope IK (Inverse Kinematics) Translation of 6th axis and consequent calculation of the joints angles G2
G3
G4
G5 Top view
Perspective
G1 G0
170°
723m
m
170°
Side view
76
Front view
77
3_ Robotic Arm End Effector Design Nachi Agent
Once effector is connected to Nachi, in order to allow Nachi to draw in the center point of effect, it required to calculate the correct cordination of the center axis, due to effector center axis is 60° offset between each pen.
Effector Agent
X TCP
X TCP -0.86613190, 0.00000000, -0.49981550
End Effector
Nachi Center Axis
Effector Center Axis 90°
78
Y TCP
60°
Z TCP
0.50001100 , 0.00006667, -0.86601905 Y TCP
Z TCP
79
4_ Robot Instruction and Analysis Drawing
Chapter 4 presents the vector output of the code and the resulting drawings of the 6 axis robotic arm Nachi, drawing with four dispersion felt pens onto black pvc sheets. For each drawing a series of pie charts were created, each showing the angular-motion of one of six axis. A first set of pie charts mapping the angular motion for each axis from minimum in dark blue to the maximum in red of the angular motion. The second set of pie charts situates the angular motion of each axis in the movement constraints of the Nachi robot. The pie charts show the motion over time, starting from the top 12 oâ&#x20AC;&#x2122;clock moving forward clock-wise 360 degree. This analysis is able to support a optimization process of manufacturing efficiency. Variables like machine time and so speed and accuracy could be enhanced. Also at this point the g-code is randomly compiled and executed which means the robot might start from one end and will continue on the other side instead of continuing working its way over, which is highly visible in the pie charts high noise.
80
81
4_ Robot Instruction and Analysis Drawing
G0
G1
G2
G3
G4
Photograph
Vector Image EPS file exported from code Photograph
82
83
4_ Robot Instruction and Analysis Drawing
G0
G1
G2
G3
G4
Photograph
Photograph Vector Image EPS file exported from code
84
85
4_ Robot Instruction and Analysis Drawing
G0
G1
G2
G3
G4
Photograph
Photograph Vector Image EPS file exported from code
86
87
4_ Robot Instruction and Analysis Drawing
G0
G1
G2
G3
G4
Photograph
Photograph
88
Vector Image EPS file exported from code
89
4_ Robot Instruction and Analysis Drawing
Issue_1
Issue_2
In this first drawing attempt, the end effector was unable to draw complete straight lines between two points, due to TCP is not perfectly calibrated which caused a radial shift of the pen. The interpolation of points in the robot path with a 3 degree curve caused the anticipation of the z shifting in each last point of each curve, leaving this incomplete.
In this drawing attempt, the effector was unable to reach bottom partition of the drawing, due to the platform itself is unbalanced because the weight of Nachi, causing the platform bending of 2 degree. After the measurement the bottom partition of the paper is offset 1-2mm to the horizontal level.
Radial Error due to the imperfect calibration of the TCP
90
Plane Error due to the weekness of the wooden plate which bended with the robot weight
91
4_ Robot Instruction and Analysis Drawing
92
Issue: sixth axis calibration Solution: GCODE calibration
Issue: sixth axis calibration Solution: GCODE calibration
Issue: sixth axis calibration Solution: GCODE calibration
Issue: sixth axis calibration Solution: GCODE calibration
Issue: sixth axis calibration Solution: GCODE calibration
Issue: sixth axis calibration Solution: GCODE calibration
Issue: Z TCP axis calibration Solution: GCODE calibration
Issue: Z TCP axis calibration Solution: GCODE calibration
Issue: Z TCP axis calibration Solution: GCODE calibration
Issue: Z TCP axis calibration Solution: GCODE calibration
Issue: Z TCP axis calibration Solution: GCODE calibration
Issue: Z TCP axis calibration Solution: GCODE calibration 93
Conclusion Gaining more and more control over the code, creating a highly responsive, generative, magnetic field behaviour like working script, combined with branches of notions also known from swarm intelligence theory, was a logic consequence as time went by. Fast simulation and visualization made quick progress in the digital world possible. Moving forward translating output of the script into the G-Code to be physically drawn by the robot brought up many new challenges which urged to be understood and their solutions fed back into the code to optimize and drive to perfection. 1. A main challenge was to calibrate the offset of the robots TCP: Because the customized endeffector has four radial outward oriented tool tips the TCP could not be used as default center. The codes interpolation had to be offseted and rotated into four different directions. 2. The physical mounting of the robot created inaccuracies executing and driving the robot. 3. A non fixed canvas enables for exact calibration of the center point of the drawing but creates inconsistencies in the level of the canvas plate, which also led to a necessary recalibration of each of four pens. 4. An unsolved challenge was the spheric notion of the robots operation space, which is caused by not accurately mapping the G-Code to the planar digital canvas of the robots firmware. 5. Differenciation between points and lines. The interpolation of the NACHI compiler, really interpolates all the path points, each line of the G-Code with an curve third or even fifth grade as itâ&#x20AC;&#x2122;s tool path. Since the drawing is supposed to be on a planar surface, already
94
sharp edges will be round and just used as point to pass through instead of treating such as a point to stop and move into a direction with different tangent. Of course, the robot needs to be instructed to go move in z-axis at some point, otherwise there will be one continues line instead of line segments with a start point and end point. The problem with interpolation is exactly the same in this case, just in z direction. Little hooks on the ends of the line segments, or even a broke tool tip is a result of this type of compiling. There are many great and complex behaviours which are almost perfectly controllable and translateable in code, but feeding back real world conditions into code is crucial in a context of computer aided manufacturing. Therefor understanding the machine in depth and using the right medium to feed back information to the code is fundamental. Creating a rigid high performing and to the thousands of decimals calculateable code is one thing, making it able to respond to a constantly changing and absolutely non-calculateable surrounding world the other. Challenge accepted!