From 0e2cb98f7ba90a4e0a0cf94182ebd8543943552a Mon Sep 17 00:00:00 2001 From: Amanda Ghassaei <amandaghassaei@gmail.com> Date: Mon, 29 Jun 2015 15:38:52 -0700 Subject: [PATCH] basic cam working again --- js/cam/GCodeExporter.js | 132 ----- js/cam/assemblers/Assembler.js | 494 +++++++++--------- js/cam/assemblers/Component.js | 160 +++--- js/cam/assemblers/DualStaplerAssembler.js | 12 - js/cam/assemblers/StaplerAssembler.js | 154 +++--- js/cam/cam.js | 581 +++++++++++----------- js/cam/processes/GCodeExporter.js | 137 +++++ js/cam/{ => processes}/ShopbotExporter.js | 0 js/cam/{ => processes}/TinyGExporter.js | 0 js/main.js | 24 +- js/menus/Navbar.js | 2 +- js/menus/templates/CamMenuView.html | 4 +- js/models/AppState.js | 2 + js/{models => plists}/PList.js | 30 +- js/simulation/electronics/eCell.js | 3 + js/simulation/electronics/eSim.js | 3 + js/simulation/electronics/eSimEngine.js | 3 + js/three/ThreeView.js | 6 +- 18 files changed, 905 insertions(+), 842 deletions(-) delete mode 100644 js/cam/GCodeExporter.js delete mode 100644 js/cam/assemblers/DualStaplerAssembler.js create mode 100644 js/cam/processes/GCodeExporter.js rename js/cam/{ => processes}/ShopbotExporter.js (100%) rename js/cam/{ => processes}/TinyGExporter.js (100%) rename js/{models => plists}/PList.js (92%) create mode 100644 js/simulation/electronics/eCell.js create mode 100644 js/simulation/electronics/eSim.js create mode 100644 js/simulation/electronics/eSimEngine.js diff --git a/js/cam/GCodeExporter.js b/js/cam/GCodeExporter.js deleted file mode 100644 index 8ccc6761..00000000 --- a/js/cam/GCodeExporter.js +++ /dev/null @@ -1,132 +0,0 @@ -/** - * Created by aghassaei on 3/10/15. - */ - -function GCodeExporter() { - //keep track of speeds for F commands - this.postSpeed = null; - this.animationSpeed = null; -} - -GCodeExporter.prototype.makeHeader = function(){ - var data = ""; - if (globals.lattice.get("units") == "inches") data += this.addLine("G20", [], "units inches"); - else data += this.addLine("G21", [], "units mm"); -// data += this.addLine("G90", [], "absolute positioning"); -// data += this.addLine("G54", [], "work offset"); -//// data += this.addLine("G49", [], "cancel tool length comp"); -// data += this.addLine("G40", [], "cancel tool radius comp"); -//// data += this.addLine("M09", [], "coolant off"); - - data += this.goHome(); - - return data; -}; - -GCodeExporter.prototype.addLine = function(command, params, comment){ - var data = ""; - data += command + " "; - _.each(params, function(param){ - if (!param) return; - data += param + " "; - }); - if (comment) data += "(" + comment + ")"; - data += "\n"; - return data; -}; - -GCodeExporter.prototype.addComment = function(comment){ - return "(" + comment + ")" + "\n"; -}; - -GCodeExporter.prototype._setSpeed = function(speed){ - return "F"+ speed + "\n"; -} - -//GCodeExporter.prototype._rapidXYZ = function(x, y, z){ -// return this._goXYZ(x,y,z); -//}; - -GCodeExporter.prototype.rapidXY = function(x, y){ - var data = ""; - if (this.postSpeed != globals.cam.get("rapidSpeeds").xy) data += this._setSpeed(globals.cam.get("rapidSpeeds").xy); - return data + this._goXYZ(x, y, null); -}; - -GCodeExporter.prototype.rapidZ = function(z){ - var data = ""; - if (this.postSpeed != globals.cam.get("rapidSpeeds").z) data += this._setSpeed(globals.cam.get("rapidSpeeds").z); - return data + this._goXYZ(null, null, z); -}; - -GCodeExporter.prototype._goXYZ = function(x, y, z){ - if (x !== null) x = "X"+parseFloat(x).toFixed(3); - if (y !== null) y = "Y"+parseFloat(y).toFixed(3); - if (z !== null) z = "Z"+parseFloat(z).toFixed(3); - return this.addLine("G01", [x,y,z]); -}; - -GCodeExporter.prototype.moveXY = function(x, y){ - var data = ""; - if (this.postSpeed != globals.cam.get("feedRate").xy) data += this._setSpeed(globals.cam.get("feedRate").xy); - return data + this._goXYZ(x, y, null); -}; - -GCodeExporter.prototype.moveZ = function(z){ - var data = ""; - if (this.postSpeed != globals.cam.get("feedRate").z) data += this._setSpeed(globals.cam.get("feedRate").z); - return data + this._goXYZ(null, null, z); -}; - -GCodeExporter.prototype.goHome = function(){ - var data = this._setSpeed(globals.cam.get("rapidSpeeds").z); - return data + this._goXYZ(0,0,globals.cam.get("rapidHeight")); -}; - -GCodeExporter.prototype.makeFooter = function(){ - var data = ""; -// data += this.addLine("M30", [], "program stop"); - return data; -}; - -GCodeExporter.prototype.save = function(data){ - var blob = new Blob([data], {type: "text/plain;charset=utf-8"}); - saveAs(blob, "GCodeExport" + ".nc"); -}; - -GCodeExporter.prototype.simulate = function(line, machine, wcs, callback){ - if (line == "(get stock)"){ - machine.pickUpStock(); - return callback(); - } - if (line.substr(0,2) == "({"){ - machine.releaseStock(line.substr(1,line.length-2)); - return callback(); - } - if (line[0] == "F"){//speed - this.animationSpeed = line.split("F")[1]; - return callback(); - } - if (line == "" || line[0] == "(" || line.substr(0,3) != "G01"){ - return callback(); - } - if (line.substr(0,3) == "G01"){ - return this._simulateGetPosition(line, {xy:this.animationSpeed, z:this.animationSpeed}, machine, wcs, callback); - } else { - console.warn("problem parsing gcode: " + line); - return callback(); - } -}; - -GCodeExporter.prototype._simulateGetPosition = function(line, speed, machine, wcs, callback){ - var data = line.split(" "); - var position = {x:"",y:"",z:""}; - if (data.length<2) console.warn("problem parsing gcode " + line); - for (var i=1;i<data.length;i++){ - var item = data[i]; - if (item[0] == "X") position.x = item.substr(1); - if (item[0] == "Y") position.y = item.substr(1); - if (item[0] == "Z") position.z = item.substr(1); - } - machine.moveTo(position.x, position.y, position.z, speed, wcs, callback); -}; diff --git a/js/cam/assemblers/Assembler.js b/js/cam/assemblers/Assembler.js index 46bfb07c..41a0075e 100644 --- a/js/cam/assemblers/Assembler.js +++ b/js/cam/assemblers/Assembler.js @@ -2,252 +2,256 @@ * Created by aghassaei on 5/28/15. */ - -var assemblerMaterial = new THREE.MeshLambertMaterial({color:0xaaaaaa, shading: THREE.FlatShading, transparent:true, opacity:0.5}); - -function Assembler(){ - - this.stock = this._buildStock(); - this._positionStockRelativeToEndEffector(this.stock); - this.object3D = new THREE.Object3D(); - globals.three.sceneAdd(this.object3D); - var self = this; - this._buildAssemblerComponents(function(){ - self._configureAssemblerMovementDependencies(); - globals.three.render(); - }); - - this.setVisibility(globals.cam.isVisible()); -} - -Assembler.prototype._buildStock = function(){ - if (globals.lattice.makeSuperCell) return globals.lattice.makeSuperCell(); - return globals.lattice.makeCellForLatticeType({}); -}; - -Assembler.prototype._positionStockRelativeToEndEffector = function(){ -}; - -Assembler.prototype._buildAssemblerComponents = function(callback){ - var numMeshes = this._getTotalNumMeshes(); - if (numMeshes == 0) { - callback(); - return; +define(['underscore', 'appState', 'lattice', 'three', 'threeModel', 'cam', 'component'], function(_, appState, lattice, THREE, three, cam, Component){ + + var assemblerMaterial = new THREE.MeshLambertMaterial({color:0xaaaaaa, shading: THREE.FlatShading, transparent:true, opacity:0.5}); + + function Assembler(){ + + var self = this; + this.stock = this._buildStock(); + this._positionStockRelativeToEndEffector(this.stock); + + this.object3D = new THREE.Object3D(); + three.sceneAdd(this.object3D); + this._buildAssemblerComponents(function(){ + self._configureAssemblerMovementDependencies(); + three.render(); + }); + + this.setVisibility(cam.isVisible()); } - - function allLoaded(){ - numMeshes -= 1; - return numMeshes <= 0; - } - - var self = this; - function doAdd(geometry, name){ - self[name] = new Component(geometry, assemblerMaterial); - if (allLoaded()) callback(); - } - - this._loadSTls(doAdd); -}; - -Assembler.prototype._getTotalNumMeshes = function(){ - return 0; -}; - -Assembler.prototype._configureAssemblerMovementDependencies = function(){ -}; - -Assembler.prototype.setVisibility = function(visible){ - this.object3D.visible = visible; - this._setTranslucent(); - globals.three.render(); -}; - -Assembler.prototype._setTranslucent = function(){ - //todo make stock transparent - if (globals.appState.get("currentTab") == "cam"){ - assemblerMaterial.transparent = true; - } else { - assemblerMaterial.transparent = false; - } -}; - - - - - -Assembler.prototype.postProcess = function(data, exporter){//override in subclasses - - var rapidHeight = globals.cam.get("rapidHeight"); - var safeHeight = globals.cam.get("safeHeight"); - var wcs = globals.cam.get("originPosition"); - - var stockPosition = globals.cam.get("stockPosition"); - var stockNum = 0;//position of stock in stock array - var multStockPositions = globals.cam.get("multipleStockPositions"); - var stockSeparation = globals.cam.get("stockSeparation"); - var stockArraySize = globals.cam.get("stockArraySize"); - var self = this; - - globals.lattice.rasterCells(globals.cam._getOrder(globals.cam.get("camStrategy")), function(cell){ - if (!cell) return; - if (this.stockAttachedToEndEffector){ - data += self._postGetStock(exporter); + + Assembler.prototype._buildStock = function(callback){ + lattice.makeCellForLatticeType({}, callback); + }; + + Assembler.prototype._positionStockRelativeToEndEffector = function(stock){ + }; + + Assembler.prototype._buildAssemblerComponents = function(callback){ + var numMeshes = this._getTotalNumMeshes(); + if (numMeshes == 0) { + callback(); + return; + } + + function allLoaded(){ + numMeshes -= 1; + return numMeshes <= 0; + } + + var self = this; + function doAdd(geometry, name){ + self[name] = new Component(geometry, assemblerMaterial); + if (allLoaded()) callback(); + } + + this._loadSTls(doAdd); + }; + + Assembler.prototype._getTotalNumMeshes = function(){ + return 0; + }; + + Assembler.prototype._configureAssemblerMovementDependencies = function(){ + }; + + Assembler.prototype.setVisibility = function(visible){ + this.object3D.visible = visible; + this._setTranslucent(); + three.render(); + }; + + Assembler.prototype._setTranslucent = function(){ + //todo make stock transparent + if (appState.get("currentTab") == "cam"){ + assemblerMaterial.transparent = true; } else { - var thisStockPosition = _.clone(stockPosition); - if (multStockPositions) { - thisStockPosition.x += stockNum % stockArraySize.y * stockSeparation; - thisStockPosition.y -= Math.floor(stockNum / stockArraySize.y) * stockSeparation; - stockNum += 1; - if (stockNum >= stockArraySize.x * stockArraySize.y) stockNum = 0; + assemblerMaterial.transparent = false; + } + }; + + + + + + Assembler.prototype.postProcess = function(data, exporter){//override in subclasses + + var rapidHeight = cam.get("rapidHeight"); + var safeHeight = cam.get("safeHeight"); + var wcs = cam.get("originPosition"); + + var stockPosition = cam.get("stockPosition"); + var stockNum = 0;//position of stock in stock array + var multStockPositions = cam.get("multipleStockPositions"); + var stockSeparation = cam.get("stockSeparation"); + var stockArraySize = cam.get("stockArraySize"); + var self = this; + + lattice.rasterCells(cam._getOrder(cam.get("camStrategy")), function(cell){ + if (!cell) return; + if (this.stockAttachedToEndEffector){ + data += self._postGetStock(exporter); + } else { + var thisStockPosition = _.clone(stockPosition); + if (multStockPositions) { + thisStockPosition.x += stockNum % stockArraySize.y * stockSeparation; + thisStockPosition.y -= Math.floor(stockNum / stockArraySize.y) * stockSeparation; + stockNum += 1; + if (stockNum >= stockArraySize.x * stockArraySize.y) stockNum = 0; + } + data += self._postMoveXY(exporter, stockPosition.x-wcs.x, stockPosition.y-wcs.y); + data += self._postPickUpStock(exporter, thisStockPosition, rapidHeight, wcs, safeHeight); } - data += self._postMoveXY(exporter, stockPosition.x-wcs.x, stockPosition.y-wcs.y); - data += self._postPickUpStock(exporter, thisStockPosition, rapidHeight, wcs, safeHeight); + var cellPosition = cell.getPosition(); + data += self._postMoveXY(exporter, cellPosition.x-wcs.x, cellPosition.y-wcs.y); + data += self._postReleaseStock(cellPosition, cell, exporter, rapidHeight, wcs, safeHeight); + data += "\n"; + }); + return data; + }; + + Assembler.prototype._postMoveXY = function(exporter, x, y){ + return exporter.rapidXY(x, y); + }; + + Assembler.prototype._postPickUpStock = function(exporter, stockPosition, rapidHeight, wcs, safeHeight){ + var data = ""; + data += exporter.rapidZ(stockPosition.z-wcs.z+safeHeight); + data += exporter.moveZ(stockPosition.z-wcs.z); + data += this._postGetStock(exporter); + data += exporter.moveZ(stockPosition.z-wcs.z+safeHeight); + data += exporter.rapidZ(rapidHeight); + return data; + }; + + Assembler.prototype._postGetStock = function(exporter){ + return exporter.addComment("get stock"); + }; + + Assembler.prototype._postReleaseStock = function(cellPosition, cell, exporter, rapidHeight, wcs, safeHeight){ + var data = ""; + data += exporter.rapidZ(cellPosition.z-wcs.z+safeHeight); + data += exporter.moveZ(cellPosition.z-wcs.z); + data += exporter.addComment(JSON.stringify(cell.indices)); + data += exporter.moveZ(cellPosition.z-wcs.z+safeHeight); + data += exporter.rapidZ(rapidHeight); + return data; + }; + + + + + + + Assembler.prototype.updateCellMode = function(){ + // this.stock.setMode();//todo fix this + _.each(this.stock.cells, function(cell){ + cell.setMode(); + }); + }; + + Assembler.prototype.pickUpStock = function(){ + this.stock.show(); + }; + + Assembler.prototype.releaseStock = function(index){ + lattice.showCellAtIndex(JSON.parse(index)); + this.stock.hide(); + }; + + Assembler.prototype.pause = function(){ + }; + + Assembler.prototype.moveMachine = function(){ + var origin = cam.get("originPosition"); + this.object3D.position.set(origin.x, origin.y, origin.z); + three.render(); + }; + + Assembler.prototype.moveTo = function(x, y, z, speed, wcs, callback){ + x = this._makeAbsPosition(x, wcs.x); + y = this._makeAbsPosition(y, wcs.y); + z = this._makeAbsPosition(z, wcs.z); + this._moveTo(x, y, z, speed, wcs, callback); + }; + + Assembler.prototype._moveTo = function(x, y, z, speed, wcs, callback){ + var totalThreads = 3; + function sketchyCallback(){ + totalThreads -= 1; + if (totalThreads > 0) return; + callback(); } - var cellPosition = cell.getPosition(); - data += self._postMoveXY(exporter, cellPosition.x-wcs.x, cellPosition.y-wcs.y); - data += self._postReleaseStock(cellPosition, cell, exporter, rapidHeight, wcs, safeHeight); - data += "\n"; - }); - return data; -}; - -Assembler.prototype._postMoveXY = function(exporter, x, y){ - return exporter.rapidXY(x, y); -}; - -Assembler.prototype._postPickUpStock = function(exporter, stockPosition, rapidHeight, wcs, safeHeight){ - var data = ""; - data += exporter.rapidZ(stockPosition.z-wcs.z+safeHeight); - data += exporter.moveZ(stockPosition.z-wcs.z); - data += this._postGetStock(exporter); - data += exporter.moveZ(stockPosition.z-wcs.z+safeHeight); - data += exporter.rapidZ(rapidHeight); - return data; -}; - -Assembler.prototype._postGetStock = function(exporter){ - return exporter.addComment("get stock"); -}; - -Assembler.prototype._postReleaseStock = function(cellPosition, cell, exporter, rapidHeight, wcs, safeHeight){ - var data = ""; - data += exporter.rapidZ(cellPosition.z-wcs.z+safeHeight); - data += exporter.moveZ(cellPosition.z-wcs.z); - data += exporter.addComment(JSON.stringify(cell.indices)); - data += exporter.moveZ(cellPosition.z-wcs.z+safeHeight); - data += exporter.rapidZ(rapidHeight); - return data; -}; - - - - - - -Assembler.prototype.updateCellMode = function(){ -// this.stock.setMode();//todo fix this - _.each(this.stock.cells, function(cell){ - cell.setMode(); - }); -}; - -Assembler.prototype.pickUpStock = function(){ - this.stock.show(); -}; - -Assembler.prototype.releaseStock = function(index){ - globals.lattice.showCellAtIndex(JSON.parse(index)); - this.stock.hide(); -}; - -Assembler.prototype.pause = function(){ -}; - -Assembler.prototype.moveMachine = function(){ - var origin = globals.cam.get("originPosition"); - this.object3D.position.set(origin.x, origin.y, origin.z); - globals.three.render(); -}; - -Assembler.prototype.moveTo = function(x, y, z, speed, wcs, callback){ - x = this._makeAbsPosition(x, wcs.x); - y = this._makeAbsPosition(y, wcs.y); - z = this._makeAbsPosition(z, wcs.z); - this._moveTo(x, y, z, speed, wcs, callback); -}; - -Assembler.prototype._moveTo = function(x, y, z, speed, wcs, callback){ - var totalThreads = 3; - function sketchyCallback(){ - totalThreads -= 1; - if (totalThreads > 0) return; - callback(); - } - var startingPos = {x:this.xAxis.getPosition(), y:this.yAxis.getPosition(), z:this.zAxis.getPosition()}; - speed = this._normalizeSpeed(startingPos, x, y, this._reorganizeSpeed(speed)); - this.xAxis.moveTo(this._makeAxisVector(x, "x"), speed.x, sketchyCallback); - this.yAxis.moveTo(this._makeAxisVector(y, "y"), speed.y, sketchyCallback); - this.zAxis.moveTo(this._makeAxisVector(z, "z"), speed.z, sketchyCallback); -}; - -Assembler.prototype._makeAbsPosition = function(target, wcs){ - if (target == "" || target == null || target === undefined) return null; - return parseFloat(target)+wcs; -}; - -Assembler.prototype._reorganizeSpeed = function(speed){ - var newSpeed = {}; - newSpeed.x = speed.xy; - newSpeed.y = speed.xy; - newSpeed.z = speed.z; - return newSpeed; -}; - -Assembler.prototype._normalizeSpeed = function(startingPos, x, y, speed){//xy moves need speed normalization - var normSpeed = {}; - if (x == "" || y == "") return speed; - var deltaX = x-startingPos.x; - var deltaY = y-startingPos.y; - var totalDistance = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)); - if (totalDistance == 0) return speed; - normSpeed.x = Math.abs(deltaX/totalDistance*speed.x); - normSpeed.y = Math.abs(deltaY/totalDistance*speed.y); - normSpeed.z = speed.z; - return normSpeed; -}; - -Assembler.prototype._makeAxisVector = function(position, axis){ - switch (axis){ - case "x": - return {x:position, y:0, z:0}; - case "y": - return {x:0, y:position, z:0}; - case "z": - return {x:0, y:0, z:position}; - default: - console.warn(axis + " axis not recognized"); - return null; - } -}; - - - - - - -Assembler.prototype.destroy = function(){ - this.stock.destroy(); - this.zAxis.destroy(); - this.xAxis.destroy(); - this.yAxis.destroy(); - this.frame.destroy(); - this.substrate.destroy(); - globals.three.sceneRemove(this.object3D); - this.stock = null; - this.zAxis = null; - this.xAxis = null; - this.yAxis = null; - this.frame = null; - this.substrate = null; - this.object3D = null; -}; + var startingPos = {x:this.xAxis.getPosition(), y:this.yAxis.getPosition(), z:this.zAxis.getPosition()}; + speed = this._normalizeSpeed(startingPos, x, y, this._reorganizeSpeed(speed)); + this.xAxis.moveTo(this._makeAxisVector(x, "x"), speed.x, sketchyCallback); + this.yAxis.moveTo(this._makeAxisVector(y, "y"), speed.y, sketchyCallback); + this.zAxis.moveTo(this._makeAxisVector(z, "z"), speed.z, sketchyCallback); + }; + + Assembler.prototype._makeAbsPosition = function(target, wcs){ + if (target == "" || target == null || target === undefined) return null; + return parseFloat(target)+wcs; + }; + + Assembler.prototype._reorganizeSpeed = function(speed){ + var newSpeed = {}; + newSpeed.x = speed.xy; + newSpeed.y = speed.xy; + newSpeed.z = speed.z; + return newSpeed; + }; + + Assembler.prototype._normalizeSpeed = function(startingPos, x, y, speed){//xy moves need speed normalization + var normSpeed = {}; + if (x == "" || y == "") return speed; + var deltaX = x-startingPos.x; + var deltaY = y-startingPos.y; + var totalDistance = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)); + if (totalDistance == 0) return speed; + normSpeed.x = Math.abs(deltaX/totalDistance*speed.x); + normSpeed.y = Math.abs(deltaY/totalDistance*speed.y); + normSpeed.z = speed.z; + return normSpeed; + }; + + Assembler.prototype._makeAxisVector = function(position, axis){ + switch (axis){ + case "x": + return {x:position, y:0, z:0}; + case "y": + return {x:0, y:position, z:0}; + case "z": + return {x:0, y:0, z:position}; + default: + console.warn(axis + " axis not recognized"); + return null; + } + }; + + + + + + + Assembler.prototype.destroy = function(){ + this.stock.destroy(); + this.zAxis.destroy(); + this.xAxis.destroy(); + this.yAxis.destroy(); + this.frame.destroy(); + this.substrate.destroy(); + three.sceneRemove(this.object3D); + this.stock = null; + this.zAxis = null; + this.xAxis = null; + this.yAxis = null; + this.frame = null; + this.substrate = null; + this.object3D = null; + }; + + return Assembler; +}); diff --git a/js/cam/assemblers/Component.js b/js/cam/assemblers/Component.js index 207f91e0..9fa4e15b 100644 --- a/js/cam/assemblers/Component.js +++ b/js/cam/assemblers/Component.js @@ -3,87 +3,91 @@ */ -function Component(geometry, material){ - this.object3D = new THREE.Mesh(geometry, material); -} - -Component.prototype.getPosition = function(){ - return this.object3D.position.clone(); -}; - -Component.prototype.getObject3D = function(){ - return this.object3D; -}; - -Component.prototype.addChild = function(child){ - this.object3D.add(child.getObject3D()); -}; - -Component.prototype.moveTo = function(target, speed, callback){ - var currentPosition = this.getPosition(); - var diff = _.clone(target); - _.each(_.keys(target), function(key){ - diff[key] -= currentPosition[key]; - }); - - var diffLength = this._getLength(diff); - var increment = speed/25*globals.cam.get("simSpeed"); - - if (increment == 0 || diffLength == 0) { - if (callback) callback(); - return; +define(['underscore', 'cam', 'three'], function(_, cam, THREE){ + + function Component(geometry, material){ + this.object3D = new THREE.Mesh(geometry, material); } - increment = Math.max(increment, 0.00001);//need to put a min on the increment - otherwise this stalls out with floating pt tol - - var incrementVector = diff; - _.each(_.keys(incrementVector), function(key){ - incrementVector[key] *= increment/diffLength; - }); - - this._incrementalMove(incrementVector, target, callback); -}; - -Component.prototype._remainingDistanceToTarget = function(target){ - var position = this.getPosition(); - var dist = 0; - _.each(_.keys(target), function(key){ - dist += Math.pow(target[key] - position[key], 2); - }); - return dist; -}; - -Component.prototype._getLength = function(vector){ - var length = 0; - _.each(_.keys(vector), function(key){ - length += Math.pow(vector[key], 2); - }); - return length; -}; - -Component.prototype._incrementalMove = function(increment, target, callback){ - var self = this; - setTimeout(function(){ - var remainingDist = Math.abs(self._remainingDistanceToTarget(target)); - var nextPos; - if (remainingDist == 0) { + + Component.prototype.getPosition = function(){ + return this.object3D.position.clone(); + }; + + Component.prototype.getObject3D = function(){ + return this.object3D; + }; + + Component.prototype.addChild = function(child){ + this.object3D.add(child.getObject3D()); + }; + + Component.prototype.moveTo = function(target, speed, callback){ + var currentPosition = this.getPosition(); + var diff = _.clone(target); + _.each(_.keys(target), function(key){ + diff[key] -= currentPosition[key]; + }); + + var diffLength = this._getLength(diff); + var increment = speed/25*cam.get("simSpeed"); + + if (increment == 0 || diffLength == 0) { if (callback) callback(); return; - } else if (remainingDist < self._getLength(increment)){ - nextPos = target;//don't overshoot - } else { - nextPos = self.getPosition(); - _.each(_.keys(nextPos), function(key){ - nextPos[key] += increment[key]; - }); } + increment = Math.max(increment, 0.00001);//need to put a min on the increment - otherwise this stalls out with floating pt tol + + var incrementVector = diff; + _.each(_.keys(incrementVector), function(key){ + incrementVector[key] *= increment/diffLength; + }); + + this._incrementalMove(incrementVector, target, callback); + }; + + Component.prototype._remainingDistanceToTarget = function(target){ + var position = this.getPosition(); + var dist = 0; + _.each(_.keys(target), function(key){ + dist += Math.pow(target[key] - position[key], 2); + }); + return dist; + }; + + Component.prototype._getLength = function(vector){ + var length = 0; + _.each(_.keys(vector), function(key){ + length += Math.pow(vector[key], 2); + }); + return length; + }; + + Component.prototype._incrementalMove = function(increment, target, callback){ + var self = this; + setTimeout(function(){ + var remainingDist = Math.abs(self._remainingDistanceToTarget(target)); + var nextPos; + if (remainingDist == 0) { + if (callback) callback(); + return; + } else if (remainingDist < self._getLength(increment)){ + nextPos = target;//don't overshoot + } else { + nextPos = self.getPosition(); + _.each(_.keys(nextPos), function(key){ + nextPos[key] += increment[key]; + }); + } + + self.object3D.position.set(nextPos.x, nextPos.y, nextPos.z); + self._incrementalMove(increment, target, callback); + }, 10); + }; - console.log(nextPos); - self.object3D.position.set(nextPos.x, nextPos.y, nextPos.z); - self._incrementalMove(increment, target, callback); - }, 10); -}; + Component.prototype.destroy = function(){ + if (this.object3D && this.object3D.parent) this.object3D.parent.remove(this.object3D); + this.object3D = null; + }; -Component.prototype.destroy = function(){ - if (this.object3D && this.object3D.parent) this.object3D.parent.remove(this.object3D); - this.object3D = null; -}; \ No newline at end of file + return Component; +}); \ No newline at end of file diff --git a/js/cam/assemblers/DualStaplerAssembler.js b/js/cam/assemblers/DualStaplerAssembler.js deleted file mode 100644 index a0a9fb6b..00000000 --- a/js/cam/assemblers/DualStaplerAssembler.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Created by aghassaei on 5/28/15. - */ - -function DualStaplerAssembler(){ - StaplerAssembler.call(this); -} -DualStaplerAssembler.prototype = Object.create(StaplerAssembler.prototype); - -DualStaplerAssembler.prototype._headSTLFile = function(){ - return "assets/stls/stapler/zAxisDual.stl"; -}; \ No newline at end of file diff --git a/js/cam/assemblers/StaplerAssembler.js b/js/cam/assemblers/StaplerAssembler.js index 1e9c5e78..70ab8dcb 100644 --- a/js/cam/assemblers/StaplerAssembler.js +++ b/js/cam/assemblers/StaplerAssembler.js @@ -3,84 +3,94 @@ */ -function StaplerAssembler(){ - this.stockAttachedToEndEffector = true;//no need for "stock position" - Assembler.call(this); -} -StaplerAssembler.prototype = Object.create(Assembler.prototype); +define(['underscore', 'assembler', 'stlLoader', 'gikSuperCell'], function(_, Assembler, THREE, StockClass){ -StaplerAssembler.prototype._positionStockRelativeToEndEffector = function(stock){ - var object3D = stock.getObject3D(); - object3D.position.set((2.4803+0.2)*20, (-1.9471+0.36)*20, 1.7*20); -}; + function StaplerAssembler(){ + this.stockAttachedToEndEffector = true;//no need for "stock position" + Assembler.call(this); + } + StaplerAssembler.prototype = Object.create(Assembler.prototype); -StaplerAssembler.prototype._configureAssemblerMovementDependencies = function(){ - this.zAxis.addChild(this.stock); - this.xAxis.addChild(this.zAxis); - this.frame.addChild(this.xAxis); - this.frame.addChild(this.yAxis); - this.object3D.add(this.frame.getObject3D()); - this.object3D.add(this.substrate.getObject3D()); -}; + StaplerAssembler.prototype._buildStock = function(){ + return new StockClass({}); + }; -StaplerAssembler.prototype._getTotalNumMeshes = function(){ - return 5; -}; + StaplerAssembler.prototype._positionStockRelativeToEndEffector = function(stock){ + var object3D = stock.getObject3D(); + object3D.position.set((2.4803+0.2)*20, (-1.9471+0.36)*20, 1.7*20); + }; -StaplerAssembler.prototype._loadSTls = function(doAdd){ + StaplerAssembler.prototype._configureAssemblerMovementDependencies = function(){ + this.zAxis.addChild(this.stock); + this.xAxis.addChild(this.zAxis); + this.frame.addChild(this.xAxis); + this.frame.addChild(this.yAxis); + this.object3D.add(this.frame.getObject3D()); + this.object3D.add(this.substrate.getObject3D()); + }; - function geometryScale(geometry){ - geometry.applyMatrix(new THREE.Matrix4().makeTranslation(-4.0757, -4.3432, -6.2154)); - geometry.applyMatrix(new THREE.Matrix4().makeRotationX(Math.PI/2)); + StaplerAssembler.prototype._getTotalNumMeshes = function(){ + return 5; + }; - var unitScale = 20; - geometry.applyMatrix(new THREE.Matrix4().makeScale(unitScale, unitScale, unitScale)); - geometry.applyMatrix(new THREE.Matrix4().makeTranslation(-21, -0.63, 0)); - return geometry; - } + StaplerAssembler.prototype._loadSTls = function(doAdd){ - var loader = new THREE.STLLoader(); - loader.load("assets/stls/stapler/frame.stl", function(geometry){ - doAdd(geometryScale(geometry), "frame"); - }); - loader.load(this._headSTLFile(), function(geometry){ - doAdd(geometryScale(geometry), "zAxis"); - }); - loader.load("assets/stls/stapler/yAxis.stl", function(geometry){ - doAdd(geometryScale(geometry), "yAxis"); - }); - loader.load("assets/stls/stapler/xAxis.stl", function(geometry){ - doAdd(geometryScale(geometry), "xAxis"); - }); - loader.load("assets/stls/stapler/substrate.stl", function(geometry){ -// geometry.applyMatrix(new THREE.Matrix4().makeRotationY(Math.PI/2)); -// geometry.applyMatrix(new THREE.Matrix4().makeTranslation(0, 1.8545, -1.2598)); - doAdd(geometryScale(geometry), "substrate"); - }); -}; + function geometryScale(geometry){ + geometry.applyMatrix(new THREE.Matrix4().makeTranslation(-4.0757, -4.3432, -6.2154)); + geometry.applyMatrix(new THREE.Matrix4().makeRotationX(Math.PI/2)); -StaplerAssembler.prototype._headSTLFile = function(){ - return "assets/stls/stapler/zAxis.stl"; -}; + var unitScale = 20; + geometry.applyMatrix(new THREE.Matrix4().makeScale(unitScale, unitScale, unitScale)); + geometry.applyMatrix(new THREE.Matrix4().makeTranslation(-21, -0.63, 0)); + return geometry; + } -StaplerAssembler.prototype._moveXAxis = function(startingPos, target, axis, speed, callback){ - if (target == null || target === undefined) { - callback(); - return; - } - this._animateObjects([this.xAxis], axis, speed, startingPos, target, callback); -}; -StaplerAssembler.prototype._moveYAxis = function(startingPos, target, axis, speed, callback){ - if (target == null || target === undefined) { - callback(); - return; - } - this._animateObjects([this.yAxis], axis, speed, startingPos, target, callback); -}; -StaplerAssembler.prototype._moveZAxis = function(startingPos, target, axis, speed, callback){ - if (target == null || target === undefined) { - callback(); - return; - } - this._animateObjects([this.zAxis], axis, speed, startingPos, target, callback); -}; \ No newline at end of file + var loader = new THREE.STLLoader(); + loader.load("assets/stls/stapler/frame.stl", function(geometry){ + doAdd(geometryScale(geometry), "frame"); + }); + loader.load(this._headSTLFile(), function(geometry){ + doAdd(geometryScale(geometry), "zAxis"); + }); + loader.load("assets/stls/stapler/yAxis.stl", function(geometry){ + doAdd(geometryScale(geometry), "yAxis"); + }); + loader.load("assets/stls/stapler/xAxis.stl", function(geometry){ + doAdd(geometryScale(geometry), "xAxis"); + }); + loader.load("assets/stls/stapler/substrate.stl", function(geometry){ + // geometry.applyMatrix(new THREE.Matrix4().makeRotationY(Math.PI/2)); + // geometry.applyMatrix(new THREE.Matrix4().makeTranslation(0, 1.8545, -1.2598)); + doAdd(geometryScale(geometry), "substrate"); + }); + }; + + StaplerAssembler.prototype._headSTLFile = function(){ + return "assets/stls/stapler/zAxis.stl"; + }; + + StaplerAssembler.prototype._moveXAxis = function(startingPos, target, axis, speed, callback){ + if (target == null || target === undefined) { + callback(); + return; + } + this._animateObjects([this.xAxis], axis, speed, startingPos, target, callback); + }; + StaplerAssembler.prototype._moveYAxis = function(startingPos, target, axis, speed, callback){ + if (target == null || target === undefined) { + callback(); + return; + } + this._animateObjects([this.yAxis], axis, speed, startingPos, target, callback); + }; + StaplerAssembler.prototype._moveZAxis = function(startingPos, target, axis, speed, callback){ + if (target == null || target === undefined) { + callback(); + return; + } + this._animateObjects([this.zAxis], axis, speed, startingPos, target, callback); + }; + + + return StaplerAssembler; +}); \ No newline at end of file diff --git a/js/cam/cam.js b/js/cam/cam.js index 3d3d69ca..3cadcdea 100644 --- a/js/cam/cam.js +++ b/js/cam/cam.js @@ -2,289 +2,314 @@ * Created by aghassaei on 3/10/15. */ -Cam = Backbone.Model.extend({ - - defaults: { - camStrategy: "raster", - placementOrder: "XYZ",//used for raster strategy entry - camProcess: "gcode", - machineName: "stapler", - assembler: null, - exporter: null, - - dataOut: "", - needsPostProcessing: true, - editsMadeToProgram: false,//warn the user that they will override changes - - rapidHeight: 6,//always store relative to origin - rapidHeightRelative: true, - safeHeight: 0.5,//inches above stock or assembly, when feed rate should slow - - origin: null, - originPosition: new THREE.Vector3(20,0,0),//in abs coordinates - stock: null, - stockPosition: new THREE.Vector3(20,0,0),//in abs coordinates - stockPositionRelative: true, - stockFixed: false,//stock is fixed position from origin - multipleStockPositions: false, - stockArraySize: {x:4, y:4}, - stockSeparation: 2.78388, - - rapidSpeeds:{xy: 3, z: 2},//rapids at clearance height - feedRate:{xy: 0.1, z: 0.1},//speed when heading towards assembly - - simLineNumber: 0,//used for stock simulation, reading through gcode - simSpeed: 4//#X times real speed - }, - - initialize: function(){ - - _.bindAll(this, "postProcess"); - - //bind events - this.listenTo(globals.appState, "change:currentTab", this._tabChanged); - this.listenTo(this, "change:originPosition", this._moveOrigin); - this.listenTo(this, "change:stockPosition", this._moveStock); - this.listenTo(this, - "change:originPosition " + - "change:stockPosition " + - "change:feedRate " + - "change:rapidSpeeds " + - "change:camProcess " + - "change:camStrategy " + - "change:placementOrder " + - "change:safeHeight " + - "change:stockArraySize " + - "change:stockSeparation " + - "change:multipleStockPositions " + - "change:rapidHeight " + - "change:machineName", - this._setNeedsPostProcessing); - this.listenTo(globals.lattice, - "change:numCells " + - "change:units " + - "change:scale " + - "change:cellType " + - "change:connectionType", - this._setNeedsPostProcessing); - this.listenTo(globals.appState, "change:stockSimulationPlaying", this._stockSimulation); - - this.listenTo(globals.lattice, "change:partType", this._updatePartType); - this.listenTo(globals.lattice, "change:cellType change:connectionType", this._updateCellType); - this.listenTo(globals.appState, "change:cellMode", this._updateCellMode); - this.listenTo(this, "change:machineName", this.selectMachine); - -// this._initOriginAndStock(); - }, - - selectMachine: function(){ - var machineName = this.get("machineName"); - if (this.get("assembler")) this.get("assembler").destroy(); - this.set("assembler", null); - this._setMachineDefaults(machineName); - if (machineName == "shopbot"){ - this.set("assembler", new Shopbot()); - } else if (machineName == "handOfGod"){ - this.set("assembler", new God()); - } else if (machineName == "oneBitBot"){ - this.set("assembler", new OneBitBot()); - } else if (machineName == "stapler"){ - this.set("assembler", new StaplerAssembler()); - } else if (machineName == "staplerDual"){ - this.set("assembler", new DualStaplerAssembler()); - } else{ - console.warn("selected assembler not recognized"); - } - }, - - _setMachineDefaults: function(machineName){ - if (globals.plist.allMachineDefaults[machineName]){ - _.each(_.keys(globals.plist.allMachineDefaults[machineName]), function(key){ - globals.cam.set(key, globals.plist.allMachineDefaults[machineName][key], {silent:true}); +define(['underscore', 'backbone', 'appState', 'latticeCAM', 'threeModel', 'plist'], function(_, Backbone, appState, lattice, three, plist){ + + var Cam = Backbone.Model.extend({ + + defaults: { + camStrategy: "raster", + placementOrder: "XYZ",//used for raster strategy entry + camProcess: "gcode", + machineName: "stapler", + assembler: null, + exporter: null, + + dataOut: "", + needsPostProcessing: true, + editsMadeToProgram: false,//warn the user that they will override changes + + rapidHeight: 6,//always store relative to origin + rapidHeightRelative: true, + safeHeight: 0.5,//inches above stock or assembly, when feed rate should slow + + origin: null, + originPosition: new THREE.Vector3(20,0,0),//in abs coordinates + stock: null, + stockPosition: new THREE.Vector3(20,0,0),//in abs coordinates + stockPositionRelative: true, + stockFixed: false,//stock is fixed position from origin + multipleStockPositions: false, + stockArraySize: {x:4, y:4}, + stockSeparation: 2.78388, + + rapidSpeeds:{xy: 3, z: 2},//rapids at clearance height + feedRate:{xy: 0.1, z: 0.1},//speed when heading towards assembly + + simLineNumber: 0,//used for stock simulation, reading through gcode + simSpeed: 4//#X times real speed + }, + + initialize: function(){ + + _.bindAll(this, "postProcess"); + + //bind events + this.listenTo(appState, "change:currentTab", this._tabChanged); + this.listenTo(appState, "change:currentNav", this._navChanged); + this.listenTo(this, "change:originPosition", this._moveOrigin); + this.listenTo(this, "change:stockPosition", this._moveStock); + this.listenTo(this, + "change:originPosition " + + "change:stockPosition " + + "change:feedRate " + + "change:rapidSpeeds " + + "change:camProcess " + + "change:camStrategy " + + "change:placementOrder " + + "change:safeHeight " + + "change:stockArraySize " + + "change:stockSeparation " + + "change:multipleStockPositions " + + "change:rapidHeight " + + "change:machineName", + this._setNeedsPostProcessing); + this.listenTo(lattice, + "change:numCells " + + "change:units " + + "change:scale " + + "change:cellType " + + "change:connectionType", + this._setNeedsPostProcessing); + this.listenTo(appState, "change:stockSimulationPlaying", this._stockSimulation); + + this.listenTo(lattice, "change:partType", this._updatePartType); + this.listenTo(lattice, "change:cellType change:connectionType", this._updateCellType); + this.listenTo(appState, "change:cellMode", this._updateCellMode); + this.listenTo(this, "change:machineName", this.selectMachine); + + // this._initOriginAndStock(); + }, + + + + + + + + selectMachine: function(){ + var machineName = this.get("machineName"); + if (this.get("assembler")) this.get("assembler").destroy(); + this.set("assembler", null); + this._setMachineDefaults(machineName); + var self = this; + require([machineName], function(MachineClass){ + self.set('assembler', new MachineClass()); }); - } - }, - - makeProgramEdits: function(data){ - this.set("dataOut", data, {silent:true}); - this.set("editsMadeToProgram", true, {silent: true}); - }, - -/////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////VISUALIZATION////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - - isVisible: function(){ - var currentTab = globals.appState.get("currentTab"); - return (currentTab == "cam" || currentTab == "animate" || currentTab == "send"); - }, - - _updateCellType: function(){ - if (this.get("assembler")) this.get("assembler").updateCellType(); - this.set("machineName", "handOfGod");//todo this should go away with dynamic allocation of this model - - }, - - _updatePartType: function(){ - if (this.get("assembler")) this.get("assembler").updatePartType(); - }, - - _updateCellMode: function(){ - if (this.get("assembler")) this.get("assembler").updateCellMode(); - globals.three.render(); - }, - - _tabChanged: function(){ - this._setCAMVisibility(); - if (globals.appState.get("currentTab") != "animate") this.resetSimulation(); - }, - - _setCAMVisibility: function(){ - var visible = this.isVisible(); -// this.get("origin").visible = visible; -// this.get("stock").visible = visible; - if (visible && !this.get("assembler")) this.selectMachine(); - if (this.get("assembler")) this.get("assembler").setVisibility(visible); - if (globals.appState.get("currentNav") == "navAssemble") { - globals.appState.set("basePlaneIsVisible", !visible); - globals.appState.set("highlighterIsVisible", !visible); - } - globals.three.render(); - }, - - _initOriginAndStock: function(){//todo this is ugly - var origin = new THREE.Mesh(new THREE.SphereGeometry(1), - new THREE.MeshBasicMaterial({color:0xff0000})); - globals.three.sceneAdd(origin); - this.set("origin", origin); - this._moveOrigin(); - //init stock mesh - var stock = new THREE.Mesh(new THREE.SphereGeometry(1), - new THREE.MeshBasicMaterial({color:0xff00ff})); - globals.three.sceneAdd(stock); - this.set("stock", stock); - this._moveStock(); - this._setCAMVisibility(); - }, - - _moveOrigin: function(){ - var position = this.get("originPosition"); -// this.get("origin").position.set(position.x, position.y, position.z); - if (this.get("stockFixed")) this._updateStockPosToOrigin(position, this.previous("originPosition")); - globals.three.render(); - if (this.get("assembler")) this.get("assembler").moveMachine(); - }, - - _updateStockPosToOrigin: function(newOrigin, lastOrigin){ - var newStockPosition = _.clone(this.get("stockPosition")); - _.each(_.keys(newStockPosition), function(key){ - newStockPosition[key] += newOrigin[key] - lastOrigin[key]; - newStockPosition[key] = parseFloat(newStockPosition[key].toFixed(4)); - }); - this.set("stockPosition", newStockPosition); - }, - - _moveStock: function(){ - var position = this.get("stockPosition"); - this.get("stock").position.set(position.x, position.y, position.z); - globals.three.render(); - }, - -/////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////SIMULATION////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - - resetSimulation: function(){ - this.set("simLineNumber", 0, {silent:true}); - globals.appState.set("stockSimulationPlaying", false); - globals.three.stopAnimationLoop(); - globals.lattice.showCells(); - }, - - _stockSimulation: function(){ - if (globals.appState.get("stockSimulationPlaying")){ - globals.three.startAnimationLoop(); - var currentLine = this.get("simLineNumber"); - if (currentLine == 0) globals.lattice.hideCells(); - var allLines = this.get("dataOut").split("\n"); - if(currentLine<allLines.length){ - var self = this; - this.get("exporter").simulate(allLines[currentLine], this.get("assembler"), - this.get("originPosition"), function(){ - currentLine++; - self.set("simLineNumber", currentLine); - self._stockSimulation(); + }, + + _setMachineDefaults: function(machineName){ + var self = this; + if (plist.allMachineDefaults[machineName]){ + _.each(_.keys(plist.allMachineDefaults[machineName]), function(key){ + self.set(key, plist.allMachineDefaults[machineName][key], {silent:true}); }); + } + }, + + makeProgramEdits: function(data){ + this.set("dataOut", data, {silent:true}); + this.set("editsMadeToProgram", true, {silent: true}); + }, + + + + + + + //events + + _navChanged: function(){ + if (appState.get("currentNav") == "navAssemble") this._setToDefaults(); + }, + + _setToDefaults: function(){ + //call this each time we switch to assemble tab + var availableMachines = _.keys(plist.allMachineTypes[lattice.get("cellType")][lattice.get("connectionType")]); + if (availableMachines.indexOf(this.get("machineName")) < 0){ + this.set("machineName", availableMachines[0]); + } + }, + + _tabChanged: function(){ + this._setCAMVisibility(); + if (appState.get("currentTab") != "animate") this.resetSimulation(); + }, + + _setCAMVisibility: function(){ + var visible = this.isVisible(); + // this.get("origin").visible = visible; + // this.get("stock").visible = visible; + if (visible && !this.get("assembler")) this.selectMachine(); + if (this.get("assembler")) this.get("assembler").setVisibility(visible); + if (appState.get("currentNav") == "navAssemble") { + appState.set("basePlaneIsVisible", !visible); + appState.set("highlighterIsVisible", !visible); + } + three.render(); + }, + + _updateCellType: function(){ + if (this.get("assembler")) this.get("assembler").updateCellType(); + this.set("machineName", "handOfGod");//todo this should go away with dynamic allocation of this model + + }, + + _updatePartType: function(){ + if (this.get("assembler")) this.get("assembler").updatePartType(); + }, + + _updateCellMode: function(){ + if (this.get("assembler")) this.get("assembler").updateCellMode(); + three.render(); + }, + + + + + + + + + + //visualization + + isVisible: function(){ + var currentTab = appState.get("currentTab"); + return (currentTab == "cam" || currentTab == "animate" || currentTab == "send"); + }, + + + _initOriginAndStock: function(){//todo this is ugly + var origin = new THREE.Mesh(new THREE.SphereGeometry(1), + new THREE.MeshBasicMaterial({color:0xff0000})); + three.sceneAdd(origin); + this.set("origin", origin); + this._moveOrigin(); + //init stock mesh + var stock = new THREE.Mesh(new THREE.SphereGeometry(1), + new THREE.MeshBasicMaterial({color:0xff00ff})); + three.sceneAdd(stock); + this.set("stock", stock); + this._moveStock(); + this._setCAMVisibility(); + }, + + _moveOrigin: function(){ + var position = this.get("originPosition"); + // this.get("origin").position.set(position.x, position.y, position.z); + if (this.get("stockFixed")) this._updateStockPosToOrigin(position, this.previous("originPosition")); + three.render(); + if (this.get("assembler")) this.get("assembler").moveMachine(); + }, + + _updateStockPosToOrigin: function(newOrigin, lastOrigin){ + var newStockPosition = _.clone(this.get("stockPosition")); + _.each(_.keys(newStockPosition), function(key){ + newStockPosition[key] += newOrigin[key] - lastOrigin[key]; + newStockPosition[key] = parseFloat(newStockPosition[key].toFixed(4)); + }); + this.set("stockPosition", newStockPosition); + }, + + _moveStock: function(){ + var position = this.get("stockPosition"); + this.get("stock").position.set(position.x, position.y, position.z); + three.render(); + }, + + /////////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////SIMULATION////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////////////// + + resetSimulation: function(){ + this.set("simLineNumber", 0, {silent:true}); + appState.set("stockSimulationPlaying", false); + three.stopAnimationLoop(); + lattice.showCells(); + }, + + _stockSimulation: function(){ + if (appState.get("stockSimulationPlaying")){ + three.startAnimationLoop(); + var currentLine = this.get("simLineNumber"); + if (currentLine == 0) lattice.hideCells(); + var allLines = this.get("dataOut").split("\n"); + if(currentLine<allLines.length){ + var self = this; + this.get("exporter").simulate(allLines[currentLine], this.get("assembler"), + this.get("originPosition"), function(){ + currentLine++; + self.set("simLineNumber", currentLine); + self._stockSimulation(); + }); + } else { + //finished simulation + this.resetSimulation(); + } } else { - //finished simulation - this.resetSimulation(); + three.stopAnimationLoop(); + this.get("assembler").pause(); } - } else { - globals.three.stopAnimationLoop(); - this.get("assembler").pause(); - } - }, - -/////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////POST PROCESSING//////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - - _setNeedsPostProcessing: function(){ - this.set("needsPostProcessing", true); - }, - - postProcess: function(){ - this.set("needsPostProcessing", false); - var exporter = this._getExporter(); - - var data = ""; - data += exporter.makeHeader(); - data += "\n\n"; - data += exporter.addComment("begin program"); - data += "\n"; - - data = this.get("assembler").postProcess(data, exporter); - - data += "\n\n"; - data += exporter.addComment("end program"); - data += "\n"; - data += exporter.makeFooter(); - - this.set("dataOut", data); - this.set("editsMadeToProgram", false); - this.set("exporter", exporter); - if (!globals.appState.get("stockSimulationPlaying")) this.resetSimulation(); - return {data:data, exporter:exporter}; - }, - - _getExporter: function(){ -// var currentExporter = this.get("exporter"); - var camProcess = this.get("camProcess"); - if (camProcess == "shopbot") { - return new ShopbotExporter(); - } else if (camProcess == "gcode") { - return new GCodeExporter(); - } else if (camProcess == "tinyG"){ - return new TinyGExporter(); - } - console.warn("cam process not supported"); - return null; - }, - - _getOrder: function(strategy){ - if (strategy == "raster") return this.get("placementOrder"); - console.warn("strategy not recognized"); - return ""; - }, - - save: function(){ - if (this.get("needsPostProcessing")){ - var output = this.postProcess(); - output.exporter.save(output.data); - return; + }, + + /////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////POST PROCESSING//////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////////////// + + _setNeedsPostProcessing: function(){ + this.set("needsPostProcessing", true); + }, + + postProcess: function(){ + this.set("needsPostProcessing", false); + var self = this; + this._getExporter(function(exporter){ + var data = ""; + data += exporter.makeHeader(); + data += "\n\n"; + data += exporter.addComment("begin program"); + data += "\n"; + + data = self.get("assembler").postProcess(data, exporter); + + data += "\n\n"; + data += exporter.addComment("end program"); + data += "\n"; + data += exporter.makeFooter(); + + self.set("dataOut", data); + self.set("editsMadeToProgram", false); + self.set("exporter", exporter); + if (!appState.get("stockSimulationPlaying")) self.resetSimulation(); + }); +// return {data:data, exporter:exporter};//todo this breaks save + }, + + _getExporter: function(callback){ + // var currentExporter = this.get("exporter"); + var camProcess = this.get("camProcess"); + require([camProcess], function(ProcessClass){ + if (callback) callback(new ProcessClass()); + }); + }, + + _getOrder: function(strategy){ + if (strategy == "raster") return this.get("placementOrder"); + console.warn("strategy not recognized"); + return ""; + }, + + save: function(){ + if (this.get("needsPostProcessing")){ + var output = this.postProcess(); + output.exporter.save(output.data); + return; + } + this.get("exporter").save(this.get("dataOut")); } - this.get("exporter").save(this.get("dataOut")); - } + }); + + return new Cam(); }); \ No newline at end of file diff --git a/js/cam/processes/GCodeExporter.js b/js/cam/processes/GCodeExporter.js new file mode 100644 index 00000000..feb519a0 --- /dev/null +++ b/js/cam/processes/GCodeExporter.js @@ -0,0 +1,137 @@ +/** + * Created by aghassaei on 3/10/15. + */ + +define(['underscore', 'cam', 'lattice'], function(_, cam, lattice){ + + function GCodeExporter() { + //keep track of speeds for F commands + this.postSpeed = null; + this.animationSpeed = null; + } + + GCodeExporter.prototype.makeHeader = function(){ + var data = ""; + if (lattice.get("units") == "inches") data += this.addLine("G20", [], "units inches"); + else data += this.addLine("G21", [], "units mm"); + // data += this.addLine("G90", [], "absolute positioning"); + // data += this.addLine("G54", [], "work offset"); + //// data += this.addLine("G49", [], "cancel tool length comp"); + // data += this.addLine("G40", [], "cancel tool radius comp"); + //// data += this.addLine("M09", [], "coolant off"); + + data += this.goHome(); + + return data; + }; + + GCodeExporter.prototype.addLine = function(command, params, comment){ + var data = ""; + data += command + " "; + _.each(params, function(param){ + if (!param) return; + data += param + " "; + }); + if (comment) data += "(" + comment + ")"; + data += "\n"; + return data; + }; + + GCodeExporter.prototype.addComment = function(comment){ + return "(" + comment + ")" + "\n"; + }; + + GCodeExporter.prototype._setSpeed = function(speed){ + return "F"+ speed + "\n"; + } + + //GCodeExporter.prototype._rapidXYZ = function(x, y, z){ + // return this._goXYZ(x,y,z); + //}; + + GCodeExporter.prototype.rapidXY = function(x, y){ + var data = ""; + if (this.postSpeed != cam.get("rapidSpeeds").xy) data += this._setSpeed(cam.get("rapidSpeeds").xy); + return data + this._goXYZ(x, y, null); + }; + + GCodeExporter.prototype.rapidZ = function(z){ + var data = ""; + if (this.postSpeed != cam.get("rapidSpeeds").z) data += this._setSpeed(cam.get("rapidSpeeds").z); + return data + this._goXYZ(null, null, z); + }; + + GCodeExporter.prototype._goXYZ = function(x, y, z){ + if (x !== null) x = "X"+parseFloat(x).toFixed(3); + if (y !== null) y = "Y"+parseFloat(y).toFixed(3); + if (z !== null) z = "Z"+parseFloat(z).toFixed(3); + return this.addLine("G01", [x,y,z]); + }; + + GCodeExporter.prototype.moveXY = function(x, y){ + var data = ""; + if (this.postSpeed != cam.get("feedRate").xy) data += this._setSpeed(cam.get("feedRate").xy); + return data + this._goXYZ(x, y, null); + }; + + GCodeExporter.prototype.moveZ = function(z){ + var data = ""; + if (this.postSpeed != cam.get("feedRate").z) data += this._setSpeed(cam.get("feedRate").z); + return data + this._goXYZ(null, null, z); + }; + + GCodeExporter.prototype.goHome = function(){ + var data = this._setSpeed(cam.get("rapidSpeeds").z); + return data + this._goXYZ(0,0,cam.get("rapidHeight")); + }; + + GCodeExporter.prototype.makeFooter = function(){ + var data = ""; + // data += this.addLine("M30", [], "program stop"); + return data; + }; + + GCodeExporter.prototype.save = function(data){ + var blob = new Blob([data], {type: "text/plain;charset=utf-8"}); + saveAs(blob, "GCodeExport" + ".nc"); + }; + + GCodeExporter.prototype.simulate = function(line, machine, wcs, callback){ + if (line == "(get stock)"){ + machine.pickUpStock(); + return callback(); + } + if (line.substr(0,2) == "({"){ + machine.releaseStock(line.substr(1,line.length-2)); + return callback(); + } + if (line[0] == "F"){//speed + this.animationSpeed = line.split("F")[1]; + return callback(); + } + if (line == "" || line[0] == "(" || line.substr(0,3) != "G01"){ + return callback(); + } + if (line.substr(0,3) == "G01"){ + return this._simulateGetPosition(line, {xy:this.animationSpeed, z:this.animationSpeed}, machine, wcs, callback); + } else { + console.warn("problem parsing gcode: " + line); + return callback(); + } + }; + + GCodeExporter.prototype._simulateGetPosition = function(line, speed, machine, wcs, callback){ + var data = line.split(" "); + var position = {x:"",y:"",z:""}; + if (data.length<2) console.warn("problem parsing gcode " + line); + for (var i=1;i<data.length;i++){ + var item = data[i]; + if (item[0] == "X") position.x = item.substr(1); + if (item[0] == "Y") position.y = item.substr(1); + if (item[0] == "Z") position.z = item.substr(1); + } + machine.moveTo(position.x, position.y, position.z, speed, wcs, callback); + }; + + return GCodeExporter; +}); diff --git a/js/cam/ShopbotExporter.js b/js/cam/processes/ShopbotExporter.js similarity index 100% rename from js/cam/ShopbotExporter.js rename to js/cam/processes/ShopbotExporter.js diff --git a/js/cam/TinyGExporter.js b/js/cam/processes/TinyGExporter.js similarity index 100% rename from js/cam/TinyGExporter.js rename to js/cam/processes/TinyGExporter.js diff --git a/js/main.js b/js/main.js index f8ba4ef3..b464bbbb 100644 --- a/js/main.js +++ b/js/main.js @@ -11,6 +11,7 @@ require.config({ underscore: '../dependencies/underscore', backbone: '../dependencies/backbone', flatUI: '../dependencies/flatUI/js/flat-ui', + bootstrapSlider: '../dependencies/bootstrap-slider/bootstrap-slider', fileSaverLib: '../dependencies/loaders/FileSaver.min', //three @@ -21,9 +22,11 @@ require.config({ threeView: 'three/ThreeView', fillGeometry: 'three/FillGeometry', + //plists + plist: 'plists/PList', + //models globals: 'models/Globals', - plist: 'models/PList', appState: 'models/AppState', fileSaver: 'models/FileSaver', @@ -131,7 +134,7 @@ require.config({ optimizeMenuTemplate: 'menus/templates/OptimizationMenuView.html', assemblerMenuTemplate: 'menus/templates/AssemblerMenuView.html', camMenuTemplate: 'menus/templates/CamMenuView.html', - animateMenuTemplate: 'menus/templates/AnimationMenuView.html', + animationMenuTemplate: 'menus/templates/AnimationMenuView.html', sendMenuTemplate: 'menus/templates/SendMenuView.html', compositeMenuTemplate: 'menus/templates/CompositeMenuView.html', materialEditorMenuTemplate: 'menus/templates/MaterialEditorMenuView.html', @@ -139,11 +142,20 @@ require.config({ discoveryMenuTemplate: 'menus/templates/DiscoveryMenuView.html', //cam - cam: 'cam/cam.js', + cam: 'cam/cam', //assemblers + assembler: 'cam/assemblers/Assembler', + component: 'cam/assemblers/Component', + stapler: 'cam/assemblers/StaplerAssembler', + dualStapler: 'cam/assemblers/DualStaplerAssembler', crab: 'cam/assemblers/crab', + //processes + gcode: 'cam/processes/GCodeExporter', + shopbot: 'cam/processes/ShopbotExporter', + tinyG: 'cam/processes/TinyGExporter', + //stls (not sure why ../ is not working here?) octaFaceTrianglePartSTL: 'assets/stls/parts/OctaFaceTrianglePart.stl', octaEdgeVoxPartSTL: 'assets/stls/parts/OctaEdgeVoxPart.stl', @@ -177,6 +189,10 @@ require.config({ flatUI: { deps: ['jquery'] }, + bootstrapSlider:{ + deps: ['jquery'], + exports: '$' + }, 'socketio': { exports: 'io' } @@ -191,7 +207,7 @@ require.config({ //}; //init stuff -require(['appState', 'lattice', 'navbar', 'threeModel', 'threeView', 'flatUI', 'ribbon', 'menuWrapper'], +require(['appState', 'lattice', 'navbar', 'threeModel', 'threeView', 'flatUI', 'bootstrapSlider', 'ribbon', 'menuWrapper'], function(appState, lattice, Navbar, three, ThreeView){ new Navbar({model:appState}); diff --git a/js/menus/Navbar.js b/js/menus/Navbar.js index 715544ae..9e90c18d 100644 --- a/js/menus/Navbar.js +++ b/js/menus/Navbar.js @@ -50,7 +50,7 @@ define(['jquery', 'underscore', 'backbone', 'fileSaver', 'navViewMenu'], functio _setNavSelection: function(e){ var navSelection = $(e.target).data("menuId"); - if (navSelection == "about" || navSelection == "navAssemble") { + if (navSelection == "about") { $(e.target).blur(); return; } diff --git a/js/menus/templates/CamMenuView.html b/js/menus/templates/CamMenuView.html index 074f235a..c2df6444 100644 --- a/js/menus/templates/CamMenuView.html +++ b/js/menus/templates/CamMenuView.html @@ -15,14 +15,14 @@ Units: <div class="btn-group"> <% }); %> </ul> </div><br/><br/> -Origin (xyz): +Origin (xyz): <input data-property="originPosition" data-key="x" value="<%= originPosition.x %>" placeholder="X" class="form-control floatInput assembler" type="text"> <input data-property="originPosition" data-key="y" value="<%= originPosition.y %>" placeholder="Y" class="form-control floatInput assembler" type="text"> <input data-property="originPosition" data-key="z" value="<%= originPosition.z %>" placeholder="Z" class="form-control floatInput assembler" type="text"> <% if (!(machineName == "handOfGod")){ %><br/> <a id="manualSelectOrigin" class=" btn btn-lg btn-default btn-imageCustom<% if (manualSelectOrigin){ %> btn-selected<% } %>"><img src="assets/imgs/cursor.png"></a> <label> Manually select origin from existing cell</label><br/><br/> - <% if (!assembler.stockAttachedToEndEffector){ %> + <% if (assembler && !assembler.stockAttachedToEndEffector){ %> Stock (xyz): <input data-property="stockPosition" data-key="x" value="<%= stockPosition.x %>" placeholder="X" class="form-control floatInput assembler" type="text"> <input data-property="stockPosition" data-key="y" value="<%= stockPosition.y %>" placeholder="Y" class="form-control floatInput assembler" type="text"> diff --git a/js/models/AppState.js b/js/models/AppState.js index fa11e4e5..d83de728 100644 --- a/js/models/AppState.js +++ b/js/models/AppState.js @@ -106,6 +106,8 @@ define(['underscore', 'backbone', 'threeModel', 'three', 'plist', 'globals'], fu if (navSelection == "navDesign") { this.set("basePlaneIsVisible", true); this.set("highlighterIsVisible", true); + } else if (navSelection == "navAssemble"){ + require(['cam']); } }, diff --git a/js/models/PList.js b/js/plists/PList.js similarity index 92% rename from js/models/PList.js rename to js/plists/PList.js index 2c236ee7..969fc919 100644 --- a/js/models/PList.js +++ b/js/plists/PList.js @@ -222,8 +222,7 @@ define(['three'], function(THREE){ cube:{ face:{handOfGod: "Hand of God"}, gik: { - stapler: "Stapler", - staplerDual: "Dual Head Stapler" + stapler: "Dual Head Stapler" // handOfGod: "Hand of God" } }, @@ -240,12 +239,12 @@ define(['three'], function(THREE){ allCamProcesses: { shopbot:{ shopbot: "Shopbot (sbp)", - gcode: "G-Code" + gcode: "G-Code" }, handOfGod:{gcode: "G-Code"}, oneBitBot:{ gcode: "G-Code", - tinyG: "TinyG" + tinyG: "TinyG" }, stapler: {gcode: "G-Code"}, staplerDual: {gcode: "G-Code"} @@ -253,20 +252,19 @@ define(['three'], function(THREE){ allMachineDefaults: { shopbot:null, - handOfGod:null, - oneBitBot:null, - stapler: { + handOfGod:null, + oneBitBot:null, + stapler: { camStrategy: "raster", - placementOrder: "XYZ",//used for raster strategy entry - camProcess: "gcode", - rapidHeight:3, - rapidHeightRelative: true, - safeHeight: 0.05, - originPosition: new THREE.Vector3(0,0,0), - rapidSpeeds:{xy: 3, z: 2}, + placementOrder: "XYZ",//used for raster strategy entry + camProcess: "gcode", + rapidHeight:3, + rapidHeightRelative: true, + safeHeight: 0.05, + originPosition: new THREE.Vector3(0,0,0), + rapidSpeeds:{xy: 3, z: 2}, feedRate:{xy: 0.1, z: 0.1} - }, - staplerDual: null + } }, allScripts: { diff --git a/js/simulation/electronics/eCell.js b/js/simulation/electronics/eCell.js new file mode 100644 index 00000000..9ae6b0d7 --- /dev/null +++ b/js/simulation/electronics/eCell.js @@ -0,0 +1,3 @@ +/** + * Created by aghassaei on 6/29/15. + */ diff --git a/js/simulation/electronics/eSim.js b/js/simulation/electronics/eSim.js new file mode 100644 index 00000000..9ae6b0d7 --- /dev/null +++ b/js/simulation/electronics/eSim.js @@ -0,0 +1,3 @@ +/** + * Created by aghassaei on 6/29/15. + */ diff --git a/js/simulation/electronics/eSimEngine.js b/js/simulation/electronics/eSimEngine.js new file mode 100644 index 00000000..9ae6b0d7 --- /dev/null +++ b/js/simulation/electronics/eSimEngine.js @@ -0,0 +1,3 @@ +/** + * Created by aghassaei on 6/29/15. + */ diff --git a/js/three/ThreeView.js b/js/three/ThreeView.js index 242fb786..86b6285d 100644 --- a/js/three/ThreeView.js +++ b/js/three/ThreeView.js @@ -68,8 +68,10 @@ define(['underscore', 'backbone', 'three', 'appState', 'globals', 'lattice', 'or if (appState.get("currentTab") == "cam" && appState.get("manualSelectOrigin")){ var position = globals.highlighter.getHighlightedObjectPosition(); if (position){ - globals.cam.set("originPosition", position); - appState.set("manualSelectOrigin", false); + require(['cam'], function(cam){ + cam.set("originPosition", position); + appState.set("manualSelectOrigin", false); + }); return; } } -- GitLab