-
Amanda Ghassaei authoredAmanda Ghassaei authored
Assembler.js 9.88 KiB
/**
* Created by aghassaei on 3/10/15.
*/
Assembler = Backbone.Model.extend({
defaults: {
camStrategy: "raster",
placementOrder: "XYZ",//used for raster strategy entry
camProcess: "gcode",
machineName: "handOfGod",
machine: 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,
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
simStockNum:0//which piece of stock to pick up
},
initialize: function(options){
this.selectMachine();
_.bindAll(this, "postProcess");
//bind events
this.listenTo(options.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(options.lattice,
"change:numCells " +
"change:units " +
"change:scale " +
"change:cellType " +
"change:connectionType",
this._setNeedsPostProcessing);
this.listenTo(options.lattice, "change:scale", this._setCAMScale);
this.listenTo(dmaGlobals.appState, "change:stockSimulationPlaying", this._stockSimulation);
this.listenTo(options.lattice, "change:partType", this._updatePartType);
this.listenTo(options.lattice, "change:cellType change:connectionType", this._updateCellType);
this.listenTo(options.appState, "change:cellMode", this._updateCellMode);
this.listenTo(this, "change:machineName", this.selectMachine);
this._initOriginAndStock();
},
selectMachine: function(){
var machineName = this.get("machineName");
if (this.get("machine")) this.get("machine").destroy();
if (machineName == "shopbot"){
this.set("machine", new Shopbot());
this.set("camProcess", "shopbot");
} else if (machineName == "handOfGod"){
this.set("machine", new Shopbot());
this.set("camProcess", "gcode");
} else if (machineName == "oneBitBot"){
this.set("machine", new OneBitBot());
this.set("camProcess", "gcode");
}else console.warn("selected machine not recognized");
},
makeProgramEdits: function(data){
this.set("dataOut", data, {silent:true});
this.set("editsMadeToProgram", true, {silent: true});
},
///////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////VISUALIZATION//////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
isVisible: function(){
var currentTab = dmaGlobals.appState.get("currentTab");
return (currentTab == "cam" || currentTab == "animate" || currentTab == "send");
},
_updateCellType: function(){
this.get("machine").updateCellType();
this.set("machineName", "handOfGod");//todo this should go away with dynamic allocation of this model
},
_updatePartType: function(){
this.get("machine").updatePartType();
},
_updateCellMode: function(){
this.get("machine").setVisibility(this.isVisible());
dmaGlobals.three.render();
},
_setCAMScale: function(){
var scale = dmaGlobals.lattice.get("scale")/8;
this.get("origin").scale.set(scale, scale, scale);
this.get("stock").scale.set(scale, scale, scale);
},
_tabChanged: function(){
this._setCAMVisibility();
if (dmaGlobals.appState.get("currentTab") != "animate") this.resetSimulation();
},
_setCAMVisibility: function(){
var visible = this.isVisible();
this.get("origin").visible = visible;
this.get("stock").visible = visible;
this.get("machine").setVisibility(visible);
dmaGlobals.three.render();
},
_initOriginAndStock: function(){//todo this is ugly
var origin = new THREE.Mesh(new THREE.SphereGeometry(1),
new THREE.MeshBasicMaterial({color:0xff0000}));
dmaGlobals.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}));
dmaGlobals.three.sceneAdd(stock);
this.set("stock", stock);
this._moveStock();
this._setCAMScale();
this._setCAMVisibility();
},
_moveOrigin: function(){
var position = this.get("originPosition");
this.get("origin").position.set(position.x, position.y, position.z);
dmaGlobals.three.render();
},
_moveStock: function(){
var position = this.get("stockPosition");
this.get("stock").position.set(position.x, position.y, position.z);
dmaGlobals.three.render();
},
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////SIMULATION//////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
resetSimulation: function(){
this.set("simLineNumber", 0, {silent:true});
dmaGlobals.appState.set("stockSimulationPlaying", false);
dmaGlobals.three.stopAnimationLoop();
this.set("simStockNum", 0);
dmaGlobals.lattice.showCells();
},
_stockSimulation: function(){
if (dmaGlobals.appState.get("stockSimulationPlaying")){
dmaGlobals.three.startAnimationLoop();
var currentLine = this.get("simLineNumber");
if (currentLine == 0) dmaGlobals.lattice.hideCells();
var allLines = this.get("dataOut").split("\n");
if(currentLine<allLines.length){
var self = this;
this.get("exporter").simulate(allLines[currentLine], this.get("machine"),
this.get("originPosition"), function(){
currentLine++;
self.set("simLineNumber", currentLine);
self._stockSimulation();
});
} else {
//finished simulation
this.resetSimulation();
}
} else {
dmaGlobals.three.stopAnimationLoop();
this.get("machine").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("machine").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);
this.resetSimulation();
return {data:data, exporter:exporter};
},
_getExporter: function(){
var currentExporter = this.get("exporter");
if (this.get("camProcess") == "shopbot") {
if (currentExporter && currentExporter.constructor == ShopbotExporter){
return currentExporter;
} else {
return new ShopbotExporter();
}
} else if (this.get("camProcess") == "gcode") {
if (currentExporter && currentExporter.constructor == GCodeExporter){
return currentExporter;
} else {
return new GCodeExporter();
}
}
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;
}
this.get("exporter").save(this.get("dataOut"));
}
});