diff --git a/js/cam/Assembler.js b/js/cam/Assembler.js
index 5977aa7e47819dfa865886a9449e586395f02811..62906c6edf5b12df628ffa684e1c31aadf0c74eb 100644
--- a/js/cam/Assembler.js
+++ b/js/cam/Assembler.js
@@ -6,6 +6,7 @@ Assembler = Backbone.Model.extend({
 
     defaults: {
         camStrategy: "xRaster",
+        placementOrder: "XYZ",//used for manual strategy entry
         camProcess: "shopbot",
         machine: "shopbot",
         exporter: null,
@@ -13,15 +14,16 @@ Assembler = Backbone.Model.extend({
         needsPostProcessing: true,
         editsMadeToProgram: false,//warn the user that they will override changes
 
-        rapidHeight: 6,
-        stockHeight: 0,
+        rapidHeight: 6.6,
+        safeHeight: 0.5,//inches above stock or assembly, when feed rate should slow
+
         origin: null,
         originPosition: new THREE.Vector3(20,0,0),
         stock: null,
         stockPosition: new THREE.Vector3(20,0,0),
 
         rapidSpeeds:{xy: 3, z: 2},//rapids at clearance height
-        feedRate:{xy: 0.1, z: 0.1},//speed when heading towards assembly
+        feedRate:{xy: 0.1, z: 0.1}//speed when heading towards assembly
     },
 
     initialize: function(options){
@@ -38,7 +40,10 @@ Assembler = Backbone.Model.extend({
                 "change:feedRate " +
                 "change:rapidSpeeds " +
                 "change:camProcess " +
-                "change:camStrategy",
+                "change:camStrategy " +
+                "change:placementOrder " +
+                "change:safeHeight " +
+                "change:rapidHeight",
             this._setNeedsPostProcessing);
         this.listenTo(options.lattice,
                 "change:numCells " +
@@ -65,7 +70,7 @@ Assembler = Backbone.Model.extend({
         this._setCAMVisibility();
     },
 
-    _setCAMScale: function(scale){
+    _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);
@@ -121,6 +126,7 @@ Assembler = Backbone.Model.extend({
     _getOrder: function(strategy){
         if (strategy == "xRaster") return "XYZ";
         if (strategy == "yRaster") return "YXZ";
+        if (strategy == "manual") return this.get("placementOrder");
         console.warn("strategy not recognized");
         return "";
     },
@@ -136,28 +142,17 @@ Assembler = Backbone.Model.extend({
         data += "\n";
 
         var rapidHeight = this.get("rapidHeight");
-        var stockHeight = this.get("stockHeight");
+        var safeHeight = this.get("safeHeight");
         data += exporter.moveZ(rapidHeight);
         data += "\n";
 
         var wcs = this.get("originPosition");
         var stockPosition = this.get("stockPosition");
+        var self = this;
         dmaGlobals.lattice.rasterCells(this._getOrder(this.get("camStrategy")), function(cell){
             if (!cell) return;
-
-            data += exporter.rapidXY(stockPosition.x, stockPosition.y);
-            data += exporter.rapidZ(stockPosition.z+0.5);
-            data += exporter.moveZ(stockPosition.z);
-            data += exporter.moveZ(stockPosition.z+0.5);
-            data += exporter.rapidZ(rapidHeight);
-
-            var cellPosition = cell.getPosition();
-            data += exporter.rapidXY(cellPosition.x-wcs.x, cellPosition.y-wcs.y);
-            data += exporter.rapidZ(cellPosition.z-wcs.z+0.5);
-            data += exporter.moveZ(cellPosition.z-wcs.z);
-            data += exporter.moveZ(cellPosition.z-wcs.z+0.5);
-            data += exporter.rapidZ(rapidHeight);
-
+            data += self._grabStock(exporter, stockPosition, rapidHeight, safeHeight);
+            data += self._placeCell(cell, exporter, rapidHeight, wcs, safeHeight);
             data += "\n";
         });
         data += exporter.rapidXY(0, 0);
@@ -172,6 +167,27 @@ Assembler = Backbone.Model.extend({
         return {data:data, exporter:exporter};
     },
 
+    _grabStock: function(exporter, stockPosition, rapidHeight, safeHeight){
+        var data = "";
+        data += exporter.rapidXY(stockPosition.x, stockPosition.y);
+        data += exporter.rapidZ(stockPosition.z+safeHeight);
+        data += exporter.moveZ(stockPosition.z);
+        data += exporter.moveZ(stockPosition.z+safeHeight);
+        data += exporter.rapidZ(rapidHeight);
+        return data;
+    },
+
+    _placeCell: function(cell, exporter, rapidHeight, wcs, safeHeight){
+        var data = "";
+        var cellPosition = cell.getPosition();
+        data += exporter.rapidXY(cellPosition.x-wcs.x, cellPosition.y-wcs.y);
+        data += exporter.rapidZ(cellPosition.z-wcs.z+safeHeight);
+        data += exporter.moveZ(cellPosition.z-wcs.z);
+        data += exporter.moveZ(cellPosition.z-wcs.z+safeHeight);
+        data += exporter.rapidZ(rapidHeight);
+        return data;
+    },
+
     save: function(){
         if (this.get("needsPostProcessing")){
             var output = this.postProcess();
diff --git a/js/cam/ShopbotExporter.js b/js/cam/ShopbotExporter.js
index d6b135d1c900367e134aec203474efb900a8142d..a1f8ebdacae8c63ac50c6d821adc48049cb6b82c 100644
--- a/js/cam/ShopbotExporter.js
+++ b/js/cam/ShopbotExporter.js
@@ -64,8 +64,8 @@ ShopbotExporter.prototype.moveZ = function(z){
 };
 
 ShopbotExporter.prototype.goHome = function(){
-    var data = this.moveZ(dmaGlobals.assembler.get("rapidHeight"));
-    data += this.moveXY(0,0);
+    var data = this.rapidZ(dmaGlobals.assembler.get("rapidHeight"));
+    data += this.rapidXY(0,0);
     return data;
 };
 
diff --git a/js/menus/AssemblerMenuView.js b/js/menus/AssemblerMenuView.js
index 21b7330b35fc4be7cb69b1b53b1c3785486fee93..d3dd36ed544f1ad4dafc512eb9b4c256fd49b3ed 100644
--- a/js/menus/AssemblerMenuView.js
+++ b/js/menus/AssemblerMenuView.js
@@ -17,7 +17,21 @@ AssemblerMenuView = Backbone.View.extend({
         this.assembler = options.assembler;
 
         _.bindAll(this, "render");
+        _.bindAll(this, "_onKeyup");
         this.listenTo(this.assembler, "change", this.render);
+        $(document).bind('keyup', {state:false}, this._onKeyup);
+    },
+
+    _onKeyup: function(e){
+        if ($(".placementOrder").is(":focus")) this._updatePlacementOrder(e);
+    },
+
+    _updatePlacementOrder: function(e){
+        e.preventDefault();
+        var newVal = $(e.target).val();
+        if (newVal.length<3) return;//todo this isn't quite right
+        this.assembler.set("placementOrder", newVal);
+        this.assembler.trigger("change:placementOrder");
     },
 
     _selectCamStrategy: function(e){
@@ -32,6 +46,7 @@ AssemblerMenuView = Backbone.View.extend({
 
     render: function(){
         if (this.model.get("currentTab") != "assembler") return;
+        if ($("input").is(":focus")) return;
         this.$el.html(this.template(_.extend(this.model.toJSON(), this.assembler.toJSON())));
     },
 
@@ -54,5 +69,8 @@ AssemblerMenuView = Backbone.View.extend({
                     <% }); %>\
                 </ul>\
             </div><br/><br/>\
+            <% if (camStrategy == "manual"){ %>\
+        Manual Placement Order: &nbsp;&nbsp;<input value="<%= placementOrder %>" placeholder="Placement Order" class="form-control placementOrder" type="text"><br/><br/>\
+        <% } %>\
         ')
 });
\ No newline at end of file
diff --git a/js/menus/CamMenuView.js b/js/menus/CamMenuView.js
index 9597af63097d1569642015470fbe91b784ad13a8..2b22efe1ab3281ef34926ff6283b48f77c7d63a4 100644
--- a/js/menus/CamMenuView.js
+++ b/js/menus/CamMenuView.js
@@ -42,6 +42,8 @@ CamMenuView = Backbone.View.extend({
         else if ($(".stockPosition").is(":focus")) this._updateNumber(e, "stockPosition");
         else if ($(".rapidSpeeds").is(":focus")) this._updateNumber(e, "rapidSpeeds");
         else if ($(".feedRate").is(":focus")) this._updateNumber(e, "feedRate");
+        else if ($(".safeHeight").is(":focus")) this._updateNumber(e, "safeHeight");
+        else if ($(".rapidHeight").is(":focus")) this._updateNumber(e, "rapidHeight");
     },
 
     _updateNumber: function(e, property){
@@ -49,8 +51,11 @@ CamMenuView = Backbone.View.extend({
         var newVal = parseFloat($(e.target).val());
         if (isNaN(newVal)) return;
         var object = this.assembler.get(property);
-        object[$(e.target).data("type")] = newVal;
-        this.assembler.trigger("change:"+property);
+        if ($(e.target).data("type")) {
+            object[$(e.target).data("type")] = newVal;
+            this.assembler.trigger("change:"+property);
+        }
+        else this.assembler.set(property, newVal);
     },
 
     _save: function(e){
@@ -90,6 +95,8 @@ CamMenuView = Backbone.View.extend({
             Stock (xyz): &nbsp;&nbsp;<input data-type="x" value="<%= stockPosition.x %>" placeholder="X" class="form-control numberInput stockPosition" type="text">\
             &nbsp;<input data-type="y" value="<%= stockPosition.y %>" placeholder="Y" class="form-control numberInput stockPosition" type="text">\
             &nbsp;<input data-type="z" value="<%= stockPosition.z %>" placeholder="Z" class="form-control numberInput stockPosition" type="text"><br/><br/>\
+            Clearance Height: &nbsp;&nbsp;<input value="<%= rapidHeight %>" placeholder="Z" class="form-control numberInput rapidHeight" type="text"><br/><br/>\
+            Slowdown Height: &nbsp;&nbsp;<input value="<%= safeHeight %>" placeholder="Z" class="form-control numberInput safeHeight" type="text"><br/><br/>\
             Speeds (measured in <%= units %> per second):<br/><br/>\
             Rapids (xy, z): &nbsp;&nbsp;<input data-type="xy" value="<%= rapidSpeeds.xy %>" placeholder="XY" class="form-control numberInput rapidSpeeds" type="text">\
             &nbsp;<input data-type="z" value="<%= rapidSpeeds.z %>" placeholder="Z" class="form-control numberInput rapidSpeeds" type="text"><br/><br/>\
diff --git a/js/models/AppState.js b/js/models/AppState.js
index 19a30484022845c42bcfb428471d313888e46bca..6a17d8c69846937b0652bf500a93cbc09504aed7 100644
--- a/js/models/AppState.js
+++ b/js/models/AppState.js
@@ -130,7 +130,8 @@ AppState = Backbone.Model.extend({
 //        },
         allAssemblyStrategies: {
             xRaster: "X Raster",
-            yRaster: "Y Raster"
+            yRaster: "Y Raster",
+            manual: "Manual Entry"
         },
         allCamProcesses: {
             shopbot: "Shopbot (sbp)",
diff --git a/js/models/Lattice.js b/js/models/Lattice.js
index 936cef7da7eb0a8e8c26721c118956c142c80a74..9648a7d855a9c87b70f8ac51d3967ccd4dedce00 100644
--- a/js/models/Lattice.js
+++ b/js/models/Lattice.js
@@ -441,6 +441,13 @@ Lattice = Backbone.Model.extend({
     rasterCells: function(order, callback, var1Order, var1Dim, var2Order, var2Dim, var3Order, var3Dim){//used for CAM raster x/y/z in any order permutation
         //order is of form 'XYZ'
         var firstLetter = order.charAt(0);
+        order = order.substr(1);
+        var isNeg = false;
+        if (firstLetter == "-") {
+            isNeg = true;
+            firstLetter = order.charAt(0);
+            order = order.substr(1);
+        }
         var cells = this.get("cells");
         var newVarOrder;
         var newVarDim;
@@ -498,7 +505,6 @@ Lattice = Backbone.Model.extend({
             var1Order = newVarOrder;
             var1Dim = newVarDim;
         }
-        order = order.substr(1);
         this.rasterCells(order, callback, var1Order, var1Dim, var2Order, var2Dim, var3Order, var3Dim);
     },