r5780 - in developers/werner/cncmap: . gp2rml

werner at docs.openmoko.org werner at docs.openmoko.org
Wed Jan 6 21:23:43 CET 2010


Author: werner
Date: 2010-01-06 21:23:43 +0100 (Wed, 06 Jan 2010)
New Revision: 5780

Added:
   developers/werner/cncmap/gp2rml/
   developers/werner/cncmap/gp2rml/Makefile
   developers/werner/cncmap/gp2rml/gp2rml.c
Modified:
   developers/werner/cncmap/README
Log:
Added gp2rml, gnuplot to RML converter.



Modified: developers/werner/cncmap/README
===================================================================
--- developers/werner/cncmap/README	2010-01-06 12:07:17 UTC (rev 5779)
+++ developers/werner/cncmap/README	2010-01-06 20:23:43 UTC (rev 5780)
@@ -39,6 +39,9 @@
 align: map the model (in gnuplot format) to the workspace coordinates
 obtained from "rect". This  [...]
 
+gp2rml: generate RML commands from a file in "gnuplot" format. Machine
+parameters like speed and clearance are passed on the command line.
+
 spool: send a file to a Roland MDX-15/20 mill. (To do: progress
 reporting, halt and resume, maybe manual mode a la millp.)
 

Added: developers/werner/cncmap/gp2rml/Makefile
===================================================================
--- developers/werner/cncmap/gp2rml/Makefile	                        (rev 0)
+++ developers/werner/cncmap/gp2rml/Makefile	2010-01-06 20:23:43 UTC (rev 5780)
@@ -0,0 +1,25 @@
+#
+# gp2rml/Makefile - Build the gnuplot to RML converter
+#
+# Written 2008-2010 by Werner Almesberger
+# Copyright 2008-2010 Werner Almesberger
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+
+
+MAIN=gp2rml
+
+OBJS=gp2rml.o
+
+CFLAGS = -g -Wall -Wshadow
+LDFLAGS = -lm
+
+$(MAIN):	$(OBJS)
+#		$(CC) $(LDFLAGS) -o $(MAIN) $(OBJS)
+
+clean:
+		rm -f $(OBJS)

Added: developers/werner/cncmap/gp2rml/gp2rml.c
===================================================================
--- developers/werner/cncmap/gp2rml/gp2rml.c	                        (rev 0)
+++ developers/werner/cncmap/gp2rml/gp2rml.c	2010-01-06 20:23:43 UTC (rev 5780)
@@ -0,0 +1,193 @@
+/*
+ * gp2rml.c - Convert from gnuplot to RML
+ *
+ * Written 2010 by Werner Almesberger
+ * Copyright 2010 Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+/*
+ * When setting the pen up and pen down positions (!PZ), pen up must be a
+ * zero or positive coordinate relative to Z0 and pen down must be negative
+ * or zero.
+ *
+ * Our pen up position is defined as the maximum pen down height plus some
+ * clearance. All Z coordinates are relative to Z0.
+ *
+ * All this means that we have to set Z0 (with !ZO, that's zet-oh) such that
+ * it is between the maximum pen down and pen up. Since pen up is also defined
+ * via the maximum pen down, we have to read all coordinates before we can
+ * calculate Z0 and then emit the correct positioning commands. Yuck.
+ *
+ * We choose Z0 = maximum pen down.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+
+struct segment {
+	double x, y, z;
+	struct segment *next;
+};
+
+struct path {
+	struct segment *segments;
+	struct path *next;
+};
+
+
+static struct path *paths = NULL, *curr_path;
+static struct segment **next_seg;
+static double z_max = -1e6; /* -1 km :) */
+
+
+#define units(mm)	((int) round((mm)*40.0))
+
+
+#define alloc_type(t) \
+    ({	t *alloc_tmp = malloc(sizeof(t));	\
+	if (!alloc_tmp)				\
+		abort();			\
+	alloc_tmp; })
+
+
+static void new_path(void)
+{
+	struct path *new;
+
+	new = alloc_type(struct path);
+	if (paths)
+		curr_path->next = new;
+	else
+		paths = new;
+	curr_path = new;
+	new->segments = NULL;
+	new->next = NULL;
+	next_seg = &new->segments;
+}
+
+
+static void process_file(FILE *file)
+{
+	int lineno = 0;
+	char buf[1024];
+	double x, y, z;
+	int n;
+	struct segment *seg;
+
+	new_path();
+	while (fgets(buf, sizeof(buf), file)) {
+		lineno++;
+		if (*buf == '!')
+			continue;
+		n = sscanf(buf, "%lf %lf %lf\n", &x, &y, &z);
+		switch (n) {
+		case -1:
+			if (curr_path->segments)
+				new_path();
+			continue;
+		case 2:
+			z = 0;
+			/* fall through */
+		case 3:
+			break;
+		default:
+			fprintf(stderr, "invalid data at line %d\n", lineno);
+			exit(1);
+		}
+		seg = alloc_type(struct segment);
+		seg->x = x;
+		seg->y = y;
+		seg->z = z;
+		seg->next = NULL;
+		*next_seg = seg;
+		next_seg = &seg->next;
+		if (z_max < z)
+			z_max = z;
+	}
+}
+
+
+static void output_paths(double z_clear, double xy_speed, double z_speed)
+{
+	const struct path *path;
+	const struct segment *seg;
+
+	printf("IN;!MC1;PA;VS%f;!VZ%f\n", xy_speed, z_speed);
+	printf("!VO%d;!PZ0,%d;PU\n", units(z_max), units(z_clear));
+
+	for (path = paths; path; path = path->next) {
+		seg = path->segments; 
+		if (!seg)
+			continue;
+		printf("!PZ%d,%d;PA%d,%d;PD\n",
+		    units(seg->z-z_max), units(z_clear),
+		    units(seg->x), units(seg->y));
+		seg = seg->next;
+		while (seg) {
+			printf("!ZZ%d,%d,%d\n", units(seg->x), units(seg->y),
+			    units(seg->z-z_max));
+			seg = seg->next;
+		}
+		printf("PU\n");
+	}
+
+	printf("IN;!MC0\n");
+}
+
+
+static void usage(const char *name)
+{
+	fprintf(stderr,
+"usage: %s z_clear xy_speed z_speed [file]\n\n"
+"  z_clear   clearance above the highest peak, in mm (must be > 0)\n"
+"  xy_speed  cutting speed, in mm/s\n"
+"  z_speed   vertical speed when lowering the pen, in mm/s\n"
+    , name);
+	exit(1);
+}
+
+
+int main(int argc, const char **argv)
+{
+	FILE *file;
+	char *end;
+	int i;
+	double p[3];
+
+	switch (argc) {
+	case 4:
+		file = stdin;
+		break;
+	case 5:
+		file = fopen(argv[4], "r");
+		if (!file) {
+			perror(argv[4]);
+			return 1;
+		}
+		break;
+	default:
+		usage(*argv);
+	}
+	for (i = 0; i != 3; i++) {
+		p[i] = strtod(argv[i+1], &end);
+		if (*end || p[i] <= 0)
+			usage(*argv);
+	}
+
+	process_file(file);
+	output_paths(p[0], p[1], p[2]);
+
+	if (ferror(stdout))
+		perror("stdout");
+	if (fclose(stdout) == EOF)
+		perror("stdout");
+
+	return 0;
+}




More information about the commitlog mailing list