use of com.willwinder.universalgcodesender.gcode.util.GcodeParserException in project Universal-G-Code-Sender by winder.
the class GcodeParser method processCommand.
/**
* Process commend given an initial state. This method will not modify its
* input parameters.
*
* @param includeNonMotionStates Create gcode meta responses even if there is no motion, for example "F100" will not
* return a GcodeMeta entry unless this flag is set to true.
*/
public static List<GcodeMeta> processCommand(String command, int line, final GcodeState inputState, boolean includeNonMotionStates) throws GcodeParserException {
List<String> args = GcodePreprocessorUtils.splitCommand(command);
if (args.isEmpty())
return null;
// Initialize with original state
GcodeState state = inputState.copy();
state.commandNumber = line;
// handle M codes.
// codes = GcodePreprocessorUtils.parseCodes(args, 'M');
// handleMCode(for each codes);
List<String> fCodes = GcodePreprocessorUtils.parseCodes(args, 'F');
if (!fCodes.isEmpty()) {
try {
state.speed = Double.parseDouble(Iterables.getOnlyElement(fCodes));
} catch (IllegalArgumentException e) {
throw new GcodeParserException("Multiple F-codes on one line.");
}
}
List<String> sCodes = GcodePreprocessorUtils.parseCodes(args, 'S');
if (!sCodes.isEmpty()) {
try {
state.spindleSpeed = Double.parseDouble(Iterables.getOnlyElement(sCodes));
} catch (IllegalArgumentException e) {
throw new GcodeParserException("Multiple S-codes on one line.");
}
}
// Gather G codes.
Set<Code> gCodes = GcodePreprocessorUtils.getGCodes(args);
boolean hasAxisWords = GcodePreprocessorUtils.hasAxisWords(args);
// Error to mix group 1 (Motion) and certain group 0 (NonModal) codes (G10, G28, G30, G92)
Collection<Code> motionCodes = gCodes.stream().filter(c -> c.consumesMotion()).collect(Collectors.toList());
// 1 motion code per line.
if (motionCodes.size() > 1) {
throw new GcodeParserException(Localization.getString("parser.gcode.multiple-axis-commands") + ": " + StringUtils.join(motionCodes, ", "));
}
// If there are axis words and nothing to use them, add the currentMotionMode.
if (hasAxisWords && motionCodes.isEmpty() && state.currentMotionMode != null) {
gCodes.add(state.currentMotionMode);
}
// Apply each code to the state.
List<GcodeMeta> results = new ArrayList<>();
for (Code i : gCodes) {
if (i == UNKNOWN) {
logger.warning("An unknown gcode command was detected in: " + command);
} else {
GcodeMeta meta = handleGCode(i, args, line, state, hasAxisWords);
meta.command = command;
// Commands like 'G21' don't return a point segment.
if (meta.point != null) {
meta.point.setSpeed(state.speed);
}
results.add(meta);
}
}
// Return updated state / command.
if (results.isEmpty() && includeNonMotionStates) {
GcodeMeta meta = new GcodeMeta();
meta.state = state;
meta.command = command;
meta.code = state.currentMotionMode;
return Collections.singletonList(meta);
}
return results;
}
use of com.willwinder.universalgcodesender.gcode.util.GcodeParserException in project Universal-G-Code-Sender by winder.
the class GcodeTilerTopComponent method generateOneTile.
private void generateOneTile(double offsetX, double offsetY, PrintWriter output) {
String gcodeFile = backend.getGcodeFile().getAbsolutePath();
UnitUtils.Units u = selectedUnit(this.units.getSelectedIndex());
GcodeParser parser = new GcodeParser();
parser.addCommandProcessor(new Translator(new Position(offsetX, offsetY, 0.0, u)));
parser.addCommandProcessor(new M30Processor());
output.println(GcodeUtils.unitCommand(u) + "G90");
output.println("G0X" + offsetX + "Y" + offsetY);
try {
File file = new File(gcodeFile);
try {
try (GcodeStreamReader gsr = new GcodeStreamReader(file)) {
while (gsr.getNumRowsRemaining() > 0) {
GcodeCommand next = gsr.getNextCommand();
applyTranslation(next.getCommandString(), parser, output);
}
}
} catch (GcodeStreamReader.NotGcodeStreamFile e) {
try (FileInputStream fstream = new FileInputStream(file);
DataInputStream dis = new DataInputStream(fstream);
BufferedReader fileStream = new BufferedReader(new InputStreamReader(dis))) {
String line;
while ((line = fileStream.readLine()) != null) {
applyTranslation(line, parser, output);
}
}
}
} catch (GcodeParserException | IOException ex) {
Exceptions.printStackTrace(ex);
}
}
use of com.willwinder.universalgcodesender.gcode.util.GcodeParserException in project Universal-G-Code-Sender by winder.
the class LineSplitter method processCommand.
@Override
public List<String> processCommand(String commandString, GcodeState state) throws GcodeParserException {
List<GcodeParser.GcodeMeta> commands = GcodeParser.processCommand(commandString, 0, state);
List<String> results = new ArrayList<>();
Code code = hasLine(commands);
if (code == null) {
return Collections.singletonList(commandString);
}
SplitCommand sc = GcodePreprocessorUtils.extractMotion(code, commandString);
if (sc.remainder.length() > 0) {
results.add(sc.remainder);
}
GcodeMeta command = Iterables.getLast(commands);
if (command == null || command.point == null) {
throw new GcodeParserException("Internal parser error: missing data.");
}
// line length
Position start = state.currentPoint;
Position end = command.point.point();
Position current = start;
double length = start.distance(end);
// Check if line needs splitting.
if (length > this.maxSegmentLength) {
int numSegments = (int) Math.ceil(length / this.maxSegmentLength);
double segmentLength = length / Math.ceil(length / this.maxSegmentLength);
// Create line segments, stop before the last one which uses the end point.
for (int i = 1; i < numSegments; i++) {
double k = 1 / (length / (i * segmentLength));
double newX = start.x + k * (end.x - start.x);
double newY = start.y + k * (end.y - start.y);
double newZ = start.z + k * (end.z - start.z);
Position next = new Position(newX, newY, newZ, start.getUnits());
results.add(GcodePreprocessorUtils.generateLineFromPoints(command.code, current, next, command.state.inAbsoluteMode, null));
current = next;
}
// Add the last line point.
results.add(GcodePreprocessorUtils.generateLineFromPoints(command.code, current, end, command.state.inAbsoluteMode, null));
} else {
return Collections.singletonList(commandString);
}
return results;
}
use of com.willwinder.universalgcodesender.gcode.util.GcodeParserException in project Universal-G-Code-Sender by winder.
the class ArcExpander method processCommand.
@Override
public List<String> processCommand(String command, GcodeState state) throws GcodeParserException {
if (state.currentPoint == null)
throw new GcodeParserException(Localization.getString("parser.processor.arc.start-error"));
List<String> results = new ArrayList<>();
List<GcodeMeta> commands = GcodeParser.processCommand(command, 0, state);
// If this is not an arc, there is nothing to do.
Code c = hasArcCommand(commands);
if (c == null) {
return Collections.singletonList(command);
}
SplitCommand sc = GcodePreprocessorUtils.extractMotion(c, command);
if (sc.remainder.length() > 0) {
results.add(sc.remainder);
}
GcodeMeta arcMeta = Iterables.getLast(commands);
PointSegment ps = arcMeta.point;
Position start = state.currentPoint;
Position end = arcMeta.point.point();
List<Position> points = GcodePreprocessorUtils.generatePointsAlongArcBDring(start, end, ps.center(), ps.isClockwise(), ps.getRadius(), 0, this.length, new PlaneFormatter(ps.getPlaneState()));
// That function returns the first and last points. Exclude the first
// point because the previous gcode command ends there already.
points.remove(0);
if (convertToLines) {
// Tack the speed onto the first line segment in case the arc also
// changed the feed value.
String feed = "F" + arcMeta.point.getSpeed();
for (Position point : points) {
results.add(GcodePreprocessorUtils.generateLineFromPoints(G1, start, point, state.inAbsoluteMode, df) + feed);
start = point;
feed = "";
}
} else {
// TODO: Generate arc segments.
throw new UnsupportedOperationException("I have not implemented this.");
}
return results;
}
Aggregations