Created
October 14, 2017 05:10
-
-
Save jkramarz/f9dae208b3a11e8a74622078c3938ba6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python2 | |
import re | |
import turtle | |
import sys | |
import math | |
def to_mm(distance): | |
return distance * 0.0254; | |
def to_mils(distance): | |
return distance * 39.37008; | |
rapid = False | |
def parse_move(move_string): | |
direction = { | |
"T": "LEFT", | |
"B": "RIGHT", | |
"L": "UP", | |
"R": "DOWN", | |
"M": tuple(current_angle) | |
}[move_string[0]] | |
distance_string = move_string[1:] | |
scanner=re.Scanner([ | |
(r"z", 255), | |
(r"\|[a-y]", lambda scanner, token: ord(token[1]) + 25 - 96), | |
(r"[a-y]", lambda scanner, token: ord(token[0]) - 96), | |
(r"[0-9]+", lambda scanner, token: int(token)), | |
]) | |
distance_tokens, distance_remainder = scanner.scan(distance_string) | |
distance = sum(distance_tokens) | |
if rapid: | |
return ("RAPID_MOVE", (direction, distance)) | |
else: | |
return ("MOVE", (direction, distance)) | |
current_angle = ["DOWN", "RIGHT"] | |
def parse_angle(angle_string): | |
global current_angle | |
if angle_string == "T": | |
current_angle[1] = "LEFT" | |
elif angle_string == "B": | |
current_angle[1] = "RIGHT" | |
elif angle_string == "L": | |
current_angle[0] = "UP" | |
elif angle_string == "R": | |
current_angle[0] = "DOWN" | |
def parse_speed(speed_string): | |
return "DUNNO" | |
def parse_rapid_start(): | |
global rapid | |
rapid = True; | |
return ("RAPID_MOVE_START",) | |
def parse_rapid_end(): | |
global rapid | |
rapid = True; | |
return ("RAPID_MOVE_END",) | |
def tokenizer(command_stream): | |
scanner=re.Scanner ([ | |
(r"I", lambda scanner, token: ("INITIALIZE",)), | |
(r"CV[0-9]+000000000", lambda scanner, token: ("VECTOR_SPEED", parse_speed(token))), | |
(r"V[0-9]+G[0-9]+", lambda scanner, token: ("RASTER_SPEED", token)), | |
(r"D", lambda scanner, token: ("LASER", True)), | |
(r"U", lambda scanner, token: ("LASER", False)), | |
(r"IPP", lambda scanner, token: ("HOME",)), | |
(r"IS2S", lambda scanner, token: ("UNLOCK_RAIL",)), | |
(r"(M|B|T|L|R)((z*((\|?[a-y]+)|([0-9]{3})))|(z+))", lambda scanner, token: parse_move(token)), | |
(r"TN", lambda scanner, token: ("WTF_MOVE_START", token)), | |
(r"BN", lambda scanner, token: parse_rapid_start()), | |
(r"SE", lambda scanner, token: parse_rapid_end()), | |
(r"(B|T|L|R)", lambda scanner, token: (parse_angle(token))), | |
(r"NRBS1E", lambda scanner, token: ("JOB_START",)), | |
(r"NSE", lambda scanner, token: ("JOB_END",)), | |
(r"F", lambda scanner, token: ("FINALIZE",)), | |
]) | |
return scanner.scan(command_stream) | |
def tokens_to_gcode(tokens): | |
yield "G90" | |
absolute_horizontal = 0; | |
absolute_vertical = 0; | |
for token in results: | |
if token[0] in ("MOVE", "RAPID_MOVE"): | |
direction, distance = token[1] | |
if type(direction) is not tuple: | |
if direction == "UP": | |
absolute_vertical += distance | |
elif direction == "DOWN": | |
absolute_vertical -= distance | |
elif direction == "RIGHT": | |
absolute_horizontal += distance | |
elif direction == "LEFT": | |
absolute_horizontal -= distance | |
else: | |
if direction[0] == "UP": | |
absolute_vertical += distance | |
else: | |
absolute_vertical -= distance | |
if direction[1] == "RIGHT": | |
absolute_horizontal += distance | |
else: | |
absolute_horizontal -= distance | |
if token[0] == "MOVE": | |
yield "G1 X%3.2f Y%3.2f" % ( to_mm(absolute_horizontal), to_mm(absolute_vertical) ) | |
else: | |
yield "G0 X%3.2f Y%3.2f" % ( to_mm(absolute_horizontal), to_mm(absolute_vertical) ) | |
elif token[0] == "LASER": | |
if token[1]: | |
yield "G1 S1" | |
else: | |
yield "G1 S0" | |
yield "M2" | |
yield "M5" | |
def tokens_to_turtle(tokens): | |
turtle.mode("standard") | |
turtle.setup(600, 400) | |
wn = turtle.Screen() | |
wn.setworldcoordinates(0,-200,300,0) | |
alex = turtle.Turtle() | |
alex.penup() | |
# alex.ht() | |
alex.speed(0) | |
alex.tracer(100, 100) | |
alex.setposition(0, 0) | |
for token in results: | |
if token[0] in ("MOVE", "RAPID_MOVE"): | |
direction, distance = token[1] | |
if type(direction) is not tuple: | |
alex.setheading({ | |
"UP": 90, | |
"RIGHT": 0, | |
"DOWN": 270, | |
"LEFT": 180 | |
}[direction]) | |
alex.forward(to_mm(distance)) | |
else: | |
angle = { | |
("UP", "RIGHT"): 45, | |
("DOWN", "RIGHT"): 270+45, | |
("DOWN", "LEFT"): 180+45, | |
("UP", "LEFT"): 90+45, | |
}[direction] | |
alex.setheading(angle) | |
move_by = to_mm(distance * 1.414213562) | |
alex.forward(move_by) | |
elif token[0] == "LASER": | |
if token[1]: | |
alex.pendown() | |
else: | |
alex.penup() | |
wn.exitonclick() | |
if __name__ == "__main__": | |
with open(sys.argv[1], 'rb') as f: | |
command_stream = re.sub(r"\W", "", f.read()) | |
results, remainder = tokenizer( | |
command_stream | |
) | |
tokens_to_turtle(results) | |
for command in tokens_to_gcode(results): | |
print command |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment