Hello All,
I am involved in a project that is looking to build a 2-D gantry system.
We have at our disposal two simple stepper motor based laboratory motion

control stages. One is a linear stage and one is a rotory stage. To
get the idea of what these things look like, you can see similar
products at www.newport.com under their Motion Control line of products.
Our plan is to build a polar system, utilising the linear stage as the
radius and then mount the rotory stage on top of this to control the
angle. The goal is to position a platform under a stationary tool along
user defined Cartesian X-Y path.
We are aware that it would be just easier to use two linear stages
however we only have one linear stage and as many rotory stages we need.
Does this sound like a viable solution? Can anyone suggest an easier
solution?
And finally does anyone know of any sources (Books, articles, papers
etc.) that detail the control of such a system? Specifically we are
looking for information on how the stepper motors should be moved if we
want to move from point A to point B along a line? along a curve?
Sincerely,
James McMillan

I think that the reason you're having trouble with this
may be that you're trying to solve a problem that is
actually easier than it looks. Am I correct in assuming that
you wish to know how to control the endpoint of the gantry
moving it from point A to point B along a straight line?
If you're interested strictly in position (with no concern
about velocity or dynamics-related issues), you can solve
this using high school trig. I'll set up a simple construction
to show the general approach. If you have more details, maybe
I can put together a more complete solution and even some code.
Imagine that you have a case where the linear translation
stage lies along the x-axis. We can move the pivot point
back and forth along the x-axis and rotate the apparatus
freely around that pivot point. At the other end of an "arm"
reaching from the pivot point is some kind of end-effector.
You wish to move your end effector along a line defined in
the slope-intercept form y=m*x+b. The end-effector is some
distance r (for radius) from the pivot point.
If we want to move the end effector to some point (x,y),
we simply need to position our pivot point at some position (c,0)
on the x-axis that is distance r from where we want the
end-effector to be. Imagine an x,y point somewhere on your
coordinate system and draw a circle around it. If (x,y)
is too far away from the x-axis it never touches it
(the point (x,y) is unreachable by your apparatus).
If it's too close, it the circle cuts the baseline twice.
From this, we know that there will be two candidates for
(c, 0)... you'll have to write some logic to pick the right
one.
Okay, given y=mx+b and r = sqrt( (x-c)^2 + y^2)
(x-c)^2 + (mx+b)^2 = r^2
solving for c we have
c^2 - (2*x)*c + (1+m^2)*x^2 + 2*m*x*b + b^2 - r^2 = 0
which is a simple quadratic equation. Use the general solution
to a quadratic equation to solve for c.
This will give you the position of the linear translation
stage (and the pivot point). Solving cos(angle)=(x-c)/r
gives you the angle for the rotational stage.
Gary

Gary,
Let me explain the device a little more.
We have the linear stage (correctly stated as running along
the x-axis) and on the linear stage we have a rotory
stage which will be able to rotate on the point c,0,
where c is defined by the position of the linear stage.
For the time being this is simply a plotting device, meaning
above the gantry will be a stationary pen device capable of
up and down (z-axis movement).
The goal is to position a substrate,paper,whatever laying on the
rotary stage under the pen along various paths to draw on the
substrate images.
Now, straight lines that are parallel to the axis are simple:
Say you want to draw a line from X1,Y1 to X2,Y2 (presume the substrate
is currently position so that its X-axis is parallel with the linear stages)
Just move along the linear stage X1 units, rotage 90 degress, Move
Y1 units, put the pen down and rotate 90 if need be and move the linear
stage.
What we are having difficulty with is creating diagonal lines and arcs.
If you want an arc between 2 points of radius R, is the only way to do
this by breaking it up into a finite number of lines parallel to the
axis and then tracing out those?
or is there another method someone can think of. The key is to
remember that we have a linear stage that has a stepper motor
that steps in discrete distances and a rotory stage that steps
in discrete angles.
James
G.W. Lucas wrote:

This is a VERY cool problem, and it will teach you tons about all
kinds of motion-control and path-planning techniques.
Now, how can we help without doing the project for you?
It's all about coordinate-systems and the transformation from one
into another into a third.
If I understand correctly, you want to define a line-segment on
the paper by defining two endpoints on the paper, and then draw that
line segment. Then you want to go on to other shapes etc.
If you figure out how to write two equations that transform from
a location (X,Y) on the paper into the two variables you have (V1,V2)
where for your system, V1 = the angle of the rotary stagem and V2 the distance along the linear stage, then you can take ANY line, arc
or arbitrary shape and draw it a little piece at a time. (Hint: This
particular job is not easy since there are several answers for many
locations on the paper, and there are at least two answers for EVERY
location on the paper. Don't try it quite yet)
So, Let's get started on that first OK?
We can do it the "real" robotics way with homogeneous transformation
matricies which are not all that tough, and if you get it, you'll be
able to do almost any robot "arm" type system you a likely to come
up against.
Or we can do it specifically for THIS perticular robot configuration,
which won't help a bit on the next robot, but might be a little more
accessible for your group.
Are you ready for 4X4 transformation matricies? Do you know about
matrix operations? Would you like to do it the "real" way?
After we know more about what you are ready for, we can dive in.
This will be a really fun adventure.

--
- Alan Kilian <alank(at)timelogic.com>
Bioinformatics Applications Director, TimeLogic Corporation

James,
Well, the problem of moving the paper under
the pen is only a little different than moving
the pen over the paper. I think it's just a
matter of negating the coordinates and potentially
adding some kind of offset
xPen = -xPaper + xOffset
yPen = -yPaper + yOffset
Included below is a little snippet of C code
for generating stepper settings for drawing a
straight line between two coordinates (x0,y0)
and (x1,y1). For simplicity, I pretend that you
specify steps as if you had some kind of absolute
encoder, but you'll get the idea...
The main problem, of course, is that your stepper
motors can only "address" discrete positions which
means that you can only do absolute positioning
to a certain fixed set of points. So if you are
attempting to draw a straight line, you can
only approximate it by a series of curves. What
kind of resolution does your apparatus have?
In this case, I specified a 1mm resolution for the linear
stage and a 720 step (1/2 degree) resolution for the angular
stage. The length of the "arm" was 10cm. The program draws a straight
line from (3,3) to (5,4) and computes the error at various points
along the way. The errors all came in under 1mm. However,
in another test I tried a lower resolution rotation stage
(200 steps, 1.8 degree) and got much worse results.
Of course, the resolution isn't just a factor of how many
steps your stepper motor supports, but what kind of
reduction gearing you can apply to the motor's output.
It turns out that the algebra in my previous post was
needlessly complex. In this version, I use the following:
given a desired (x,y) for some fixed r
find point (c,0) and angle theta such that
r^2 = (x-c)^2 + y^2
x = c+r*cos(theta)
y = 0+r*sin(theta)
You'll see that the calcSettings() function is very simple.
The program below works as follows. Given two points
defining a straight line, it loops on x coordinates
generating y coordinates using y = m*x+b. Then it tries
to find the C (linear displacement) and theta (rotation
angle) values that would result in the appropriate (x,y).
Now, of course, because we have to work in the real world,
we can only position our equipment in terms of integer
step settings based on the resolution of our steppers.
So while calcSettings() produces real-valued (c,theta)
we do have to limit them to integral multiples of our
resolution. Doing so introduces some predictable position
error. This program generates a table of numbers showing the
result.
The other thing I tried to do was to generate settings
that varied only a single step or so at each stage of
the process... that's what's going on in the "factor"
loop.
One other hint is that if your line has a steep slope
(delta Y dominates), try computing x as a function of
y rather than y as a function of x.
As I said, there's still a lot of room for improvement.
Gary
The Results ------------------------------------------
Steps Position
Lin Ang X Y X err Y err Abs Err
-65, 35, 3.037, 3.007, 0.037, 0.007, 0.038
-64, 36, 3.111, 3.090, -0.027, 0.022, 0.034
-63, 36, 3.211, 3.090, -0.000, -0.015, 0.015
-62, 37, 3.283, 3.173, -0.027, 0.018, 0.033
-61, 37, 3.383, 3.173, -0.000, -0.019, 0.019
-60, 38, 3.455, 3.256, -0.028, 0.014, 0.031
-59, 38, 3.555, 3.256, -0.000, -0.022, 0.022
-58, 39, 3.626, 3.338, -0.029, 0.010, 0.031
-57, 39, 3.726, 3.338, 0.000, -0.025, 0.025
-56, 40, 3.797, 3.420, -0.029, 0.007, 0.030
-55, 40, 3.897, 3.420, 0.000, -0.028, 0.028
-54, 41, 3.967, 3.502, -0.030, 0.004, 0.030
-53, 41, 4.067, 3.502, 0.000, -0.031, 0.031
-52, 42, 4.136, 3.584, -0.031, 0.000, 0.031
-51, 42, 4.236, 3.584, 0.000, -0.034, 0.034
-50, 43, 4.304, 3.665, -0.032, -0.003, 0.032
-49, 43, 4.404, 3.665, 0.000, -0.037, 0.037
-48, 44, 4.472, 3.746, -0.032, -0.006, 0.033
-47, 44, 4.572, 3.746, 0.000, -0.040, 0.040
-46, 45, 4.639, 3.827, -0.033, -0.009, 0.034
-45, 46, 4.705, 3.907, -0.034, 0.038, 0.051
-44, 46, 4.805, 3.907, 0.000, 0.005, 0.005
-43, 47, 4.871, 3.987, -0.034, 0.035, 0.049
-42, 47, 4.971, 3.987, 0.000, 0.002, 0.002
-41, 48, 5.035, 4.067, -0.035, 0.032, 0.048
The Program --------------------------------------------------
#include <stdio.h>
#include <math.h>
// given r,x,y, find c and theta
calcSettings(
double r,
double x,
double y,
double c[2],
double theta[2])
{
double d; // discriminant
d = r*r-y*y;
if(d<0)
return -1; // unreachable point
d = sqrt(d);
c[0] = x-d;
c[1] = x+d;
theta[0] = atan2(y, x-c[0]);
theta[1] = atan2(y, x-c[1]);
return 0;
}
// given r, c, and theta, find resultant x,y
static void calcSetPoint(
double r, double c, double theta, double *x, double *y){
*x = c+r*cos(theta);
*y = r*sin(theta);
}
// convert value to its equivalent integral "steps"
static long resolve(double v, double resolution){
return (long)floor(v/resolution+0.5);
}
int
main(int argc, char *argv[]){
double r;
double sLinear;
double sAngular;
double x0, y0;
double x1, y1;
double dx, dy, m, b;
int status;
double c[2], theta[2], factor;
double x, y, px, py, qx, qy, xErr, yErr;
double pc, ptheta;
double qc, qtheta;
long pStepsL, pStepsA;
long qStepsL, qStepsA;
// arbitrary settings describing the physical apparatus
// in this case, units are in cm, though anything would work.
r = 10; // cm
sLinear = 0.1; // 1 mm. resolution
sAngular = 2*M_PI/720; // 1/2 degree resolution
// (x0,y0), (x1,y1) is the line we want to draw
x0 = 3.0;
y0 = 3.0;
x1 = 5.0;
y1 = 4.0;
dx = x1-x0;
dy = y1-y0;
m = dy/dx;
b = y0-m*x0;
status = calcSettings(r, x0, y0, c, theta);
pStepsL = resolve(c[0], sLinear);
pStepsA = resolve(theta[0], sAngular);
pc = pStepsL*sLinear;
ptheta = pStepsA*sAngular;
calcSetPoint(r, pStepsL*sLinear, pStepsA*sAngular, &px, &py);
printf(" Lin Ang X Y X err Y err Abs err\n");
xErr = px-x0;
yErr = py-y0;
printf("%4d, %4d, %6.3f, %6.3f, %6.3f, %6.3f, %6.3f\n",
pStepsL, pStepsA, px, py, xErr, yErr, sqrt(xErr*xErr+yErr*yErr));
while(1){
factor = 4;
do{
if(dx>0){
x = px+sLinear*factor;
}else{
x = px-sLinear*factor;
}
y = m*x+b;
calcSettings(r, x, y, c, theta);
qStepsL = resolve(c[0], sLinear);
qStepsA = resolve(theta[0], sAngular);
factor/=2;
// now compare previous results (pStep) to query (qStep)
}while(fabs(qStepsL-pStepsL)>1 || fabs(qStepsA-pStepsA)>1);
qc = qStepsL*sLinear;
qtheta = qStepsA*sAngular;
calcSetPoint(r, qc, qtheta, &qx, &qy);
xErr = qx-x;
yErr = qy-y;
printf("%4d, %4d, %6.3f, %6.3f, %6.3f, %6.3f, %6.3f\n",
qStepsL, qStepsA, qx, qy, xErr, yErr, sqrt(xErr*xErr+yErr*yErr));
if(dx>0){
if(qx>=x1)
break;
}else{
if(qx<=x1)
break;
}
pStepsL = qStepsL;
pStepsA = qStepsA;
px = qx;
py = qy;
}
}

Polytechforum.com is a website by engineers for engineers. It is not affiliated with any of manufacturers or vendors discussed here.
All logos and trade names are the property of their respective owners.