Skip to content

Commit

Permalink
Update AutoLeveler to only warn when applying to gcode instead of on …
Browse files Browse the repository at this point in the history
…start

AutoLeveler apply to gcode will now remove old processors and replace instead of disabling button
Fixes for MeshLeveler relative mode (G91)
  • Loading branch information
lastacorn committed Nov 4, 2022
1 parent c55a40f commit bd57fd7
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ public class MeshLeveler implements CommandProcessor {
final private int xLen, yLen;
final private double resolution;

// Used during processing.
private double lastZHeight;
private Units unit;

public final static String ERROR_MESH_SHAPE= "Surface mesh must be a rectangular 2D array.";
Expand All @@ -54,10 +52,10 @@ public class MeshLeveler implements CommandProcessor {
public final static String ERROR_X_ASCENTION = "Found a x coordinate that isn't ascending.";

public final static String ERROR_UNEXPECTED_ARC = "The mesh leveler cannot process arcs. Enable the arc expander.";
public final static String ERROR_MISSING_POINT_DATA = "Internal parser error: missing data.";
public final static String ERROR_MISSING_POINT_DATA = "Internal parser error: missing data. ";

/**
* @param materialSurfaceHeight Z height used in offset.
* @param materialSurfaceHeightMM Z height used in offset.
* @param surfaceMesh 2D array in the format Position[x][y]
*/
public MeshLeveler(double materialSurfaceHeightMM, Position[][] surfaceMesh, Units unit) {
Expand Down Expand Up @@ -155,30 +153,36 @@ public List<String> processCommand(final String commandString, GcodeState state)

GcodeMeta command = commands.get(0);

if (command == null || command.point == null) {
throw new GcodeParserException(ERROR_MISSING_POINT_DATA);
if (command == null) {
throw new GcodeParserException(ERROR_MISSING_POINT_DATA + commandString);
}
if (command.point == null) {
return Collections.singletonList(commandString);
}

Position start = state.currentPoint;
Position end = command.point.point();

if (start.z != end.z) {
this.lastZHeight = end.z;
}

// Get offset relative to the expected surface height.
// Visualizer normalizes everything to MM but probe mesh might be INCH
double probeScaleFactor = UnitUtils.scaleUnits(UnitUtils.Units.MM, this.unit);
double zScaleFactor = UnitUtils.scaleUnits(UnitUtils.Units.MM, state.isMetric ? Units.MM : Units.INCH);
double zPointOffset =
surfaceHeightAt(end.x / zScaleFactor, end.y / zScaleFactor) -
(this.materialSurfaceHeight / probeScaleFactor);
zPointOffset *= zScaleFactor;

double zPointOffset;
if (state.inAbsoluteMode) {
zPointOffset = surfaceHeightAt(end.x, end.y, zScaleFactor) - (this.materialSurfaceHeight / probeScaleFactor);
} else {
// TODO: If the first move in the gcode file is relative it won't properly take the materialSurfaceHeight
// into account. To fix the CommandProcessor needs to inject an adjustment before that first relative move
// happens. Until that happens the user must make sure the materialSurfaceHeight is zero.

// In relative mode we only need to adjust by the z delta between the starting and ending point
zPointOffset = surfaceHeightAt(end.x, end.y, zScaleFactor) - surfaceHeightAt(start.x, start.y, zScaleFactor);
}
zPointOffset *= zScaleFactor;

// Update z coordinate.
end.z = this.lastZHeight + zPointOffset;
//end.z /= resultScaleFactor;
end.z += zPointOffset;

String adjustedCommand = GcodePreprocessorUtils.generateLineFromPoints(
command.code, start, end, command.state.inAbsoluteMode, null);
Expand Down Expand Up @@ -214,7 +218,9 @@ protected Position[][] findBoundingArea(double x, double y) throws GcodeParserEx
* Bilinear interpolation:
* http://supercomputingblog.com/graphics/coding-bilinear-interpolation/
*/
protected double surfaceHeightAt(double x, double y) throws GcodeParserException {
protected double surfaceHeightAt(double unscaledX, double unscaledY, double zScaleFactor) throws GcodeParserException {
double x = unscaledX / zScaleFactor;
double y = unscaledY / zScaleFactor;
Position[][] q = findBoundingArea(x, y);

Position Q11 = q[0][0];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ public void applyGcodeParser(GcodeParser parser) throws Exception {

@Override
public void applyCommandProcessor(CommandProcessor commandProcessor) throws Exception {
logger.log(Level.INFO, "Applying new command processor");
logger.log(Level.INFO, String.format("Applying new command processor %s", commandProcessor.getClass().getSimpleName()));
gcp.addCommandProcessor(commandProcessor);

if (gcodeFile != null) {
Expand All @@ -489,13 +489,13 @@ public File getGcodeFile() {

@Override
public File getProcessedGcodeFile() {
logger.log(Level.INFO, "Getting processed gcode file.");
logger.log(Level.INFO, String.format("Getting processed gcode file (%s).", this.processedGcodeFile));
return this.processedGcodeFile;
}

@Override
public void send() throws Exception {
logger.log(Level.INFO, "Sending gcode file.");
logger.log(Level.INFO, String.format("Sending gcode file (%s).", this.processedGcodeFile));
// Note: there is a divide by zero error in the timer because it uses
// the rowsValueLabel that was just reset.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@ This file is part of Universal Gcode Sender (UGS).
*/
package com.willwinder.ugs.platform.surfacescanner;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.willwinder.ugs.nbm.visualizer.shared.RenderableUtils;
import com.willwinder.ugs.nbp.lib.lookup.CentralLookup;
import com.willwinder.ugs.nbp.lib.services.LocalizingService;
import com.willwinder.ugs.nbp.lib.services.TopComponentLocalizer;
import com.willwinder.universalgcodesender.gcode.GcodeParser;
import com.willwinder.universalgcodesender.gcode.processors.ArcExpander;
import com.willwinder.universalgcodesender.gcode.processors.CommentProcessor;
import com.willwinder.universalgcodesender.gcode.processors.CommandProcessor;
import com.willwinder.universalgcodesender.gcode.processors.LineSplitter;
import com.willwinder.universalgcodesender.gcode.processors.MeshLeveler;
import com.willwinder.universalgcodesender.i18n.Localization;
Expand Down Expand Up @@ -93,6 +93,8 @@ public final class AutoLevelerTopComponent extends TopComponent implements ItemL
public final static String AutoLevelerActionId = "com.willwinder.ugs.platform.surfacescanner.AutoLevelerTopComponent";
public final static String AutoLevelerCategory = LocalizingService.CATEGORY_WINDOW;

private ImmutableList<CommandProcessor> activeCommandProcessors = ImmutableList.of();

@OnStart
public static class Localizer extends TopComponentLocalizer {
public Localizer() {
Expand All @@ -119,6 +121,7 @@ public AutoLevelerTopComponent() {
yMax.addChangeListener(cl);
zMin.addChangeListener(cl);
zMax.addChangeListener(cl);
zSurface.addChangeListener(cl);
unitInch.addItemListener(this);
unitMM.addItemListener(this);

Expand Down Expand Up @@ -163,8 +166,8 @@ private void updateSettings() {
public void UGSEvent(UGSEvent evt) {
if (evt instanceof ProbeEvent) {
if (!scanner.isCollectedAllProbe()) return;
Position probe = ((ProbeEvent)evt).getProbePosition();

Position probe = ((ProbeEvent) evt).getProbePosition();
Position offset = this.settings.getAutoLevelSettings().autoLevelProbeOffset;

if (probe.getUnits() == Units.UNKNOWN || offset.getUnits() == Units.UNKNOWN) {
Expand All @@ -178,13 +181,9 @@ public void UGSEvent(UGSEvent evt) {
probe.y + offset.y,
probe.z + offset.z,
probe.getUnits()));
}

else if(evt instanceof SettingChangedEvent) {
} else if (evt instanceof SettingChangedEvent) {
updateSettings();
}

else if(evt instanceof FileStateEvent){
} else if (evt instanceof FileStateEvent) {
applyToGcode.setEnabled(true);
}
}
Expand All @@ -193,7 +192,7 @@ private double getValue(JSpinner spinner) {
Object o = spinner.getValue();
try {
return Double.parseDouble(o.toString());
} catch(Exception ignored) {
} catch (Exception ignored) {
}
return 0.0f;
}
Expand Down Expand Up @@ -225,7 +224,8 @@ private AutoLevelSettings updateScanner(Units units) {

/**
* JRadioButton's have strange state changes, so using item change.
* @param e
*
* @param e
*/
@Override
public void itemStateChanged(ItemEvent e) {
Expand Down Expand Up @@ -563,20 +563,20 @@ private void scanSurfaceButtonActionPerformed(java.awt.event.ActionEvent evt) {/

try {
scanner.enableCollectProbe(backend.getWorkPosition(), backend.getMachinePosition());

AutoLevelSettings als = settings.getAutoLevelSettings();
for (Position p : scanner.getProbeStartPositions()) {
backend.sendGcodeCommand(true, String.format("G90 G2%d G0 X%f Y%f Z%f",(p.getUnits() == Units.MM)? 1:0, p.x, p.y, p.z));
backend.sendGcodeCommand(true, String.format("G90 G2%d G0 X%f Y%f Z%f", (p.getUnits() == Units.MM) ? 1 : 0, p.x, p.y, p.z));
backend.probe("Z", als.probeSpeed, this.scanner.getProbeDistance(), u);
backend.sendGcodeCommand(true, String.format("G90 G2%d G0 Z%f",(p.getUnits() == Units.MM)? 1:0, p.z));
backend.sendGcodeCommand(true, String.format("G90 G2%d G0 Z%f", (p.getUnits() == Units.MM) ? 1 : 0, p.z));
}
} catch (Exception ex) {
Exceptions.printStackTrace(ex);
}
}//GEN-LAST:event_scanSurfaceButtonActionPerformed

private void dataViewerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dataViewerActionPerformed
List<Map<String,Double>> probeData = new ArrayList<>();
List<Map<String, Double>> probeData = new ArrayList<>();

// Collect data from grid.
if (scanner != null && scanner.getProbePositionGrid() != null) {
Expand All @@ -599,26 +599,32 @@ private void dataViewerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FI
}//GEN-LAST:event_dataViewerActionPerformed

private void applyToGcodeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_applyToGcodeActionPerformed
GcodeParser gcp = new GcodeParser();
Settings.AutoLevelSettings autoLevelSettings = this.settings.getAutoLevelSettings();

// Step 0: Get rid of comments.
gcp.addCommandProcessor(new CommentProcessor());

// Step 1: The arc processor and line processors NO LONGER need to be split!
ImmutableList.Builder<CommandProcessor> commandProcessors = ImmutableList.builder();
try {
for(CommandProcessor p : activeCommandProcessors) {
backend.removeCommandProcessor(p);
}

// Step 2: Must convert arcs to line segments.
gcp.addCommandProcessor(new ArcExpander(true, autoLevelSettings.autoLevelArcSliceLength));
// Step 1: Convert arcs to line segments.
commandProcessors.add(new ArcExpander(true, autoLevelSettings.autoLevelArcSliceLength));

// Step 3: Line splitter. No line should be longer than some fraction of "resolution"
gcp.addCommandProcessor(new LineSplitter(getValue(stepResolution)/10));
// Step 2: Line splitter. No line should be longer than some fraction of "resolution"
commandProcessors.add(new LineSplitter(getValue(stepResolution) / 10));

// Step 4: Adjust Z heights codes based on mesh offsets.
gcp.addCommandProcessor(new MeshLeveler(getValue(this.zSurface), scanner.getProbePositionGrid(), scanner.getUnits()));
// Step 3: Adjust Z heights codes based on mesh offsets.
commandProcessors.add(
new MeshLeveler(getValue(this.zSurface),
scanner.getProbePositionGrid(),
scanner.getUnits()));

try {
backend.applyGcodeParser(gcp);
applyToGcode.setEnabled(false);
activeCommandProcessors = commandProcessors.build();
for(CommandProcessor p : activeCommandProcessors) {
backend.applyCommandProcessor(p);
}
GUIHelpers.displayHelpDialog(
"The autoleveler feature is under development and may not work properly, use at your own risk.");
} catch (Exception ex) {
GUIHelpers.displayErrorDialog(ex.getMessage());
Exceptions.printStackTrace(ex);
Expand Down Expand Up @@ -650,11 +656,11 @@ private void useLoadedFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN
}//GEN-LAST:event_useLoadedFileActionPerformed

private void generateTestDataButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_generateTestDataButtonActionPerformed
if(scanner.getProbeStartPositions() == null)
if (scanner.getProbeStartPositions() == null)
return;

scanner.enableTestProbe();

// Generate some random test data.
Random random = new Random();

Expand Down Expand Up @@ -702,7 +708,6 @@ private void visibleAutoLevelerActionPerformed(java.awt.event.ActionEvent evt) {

@Override
public void componentOpened() {
GUIHelpers.displayHelpDialog("The autoleveler feature currently doesn't work properly, close the autoleveler window to disable this message in the future.");
scanner = new SurfaceScanner();
if (r == null) {
r = new AutoLevelPreview(Localization.getString("platform.visualizer.renderable.autolevel-preview"));
Expand All @@ -718,10 +723,10 @@ public void componentClosed() {
}

public void writeProperties(java.util.Properties p) {
// No properties
// No properties
}

public void readProperties(java.util.Properties p) {
// No properties
// No properties
}
}

0 comments on commit bd57fd7

Please sign in to comment.