Rotation/Movement Problem

Hi,

I don’t know if i’m over-complicating my problem but here it is:

I have a robot that needs to move around the screen controlled by a user. To do this i’ve got a spin variable to control the rotation and a move variable to control the z position. I then try to move the robot using the code:

glTranslatef(0,0,move[0]);
glRotatef(spin[0],0,1,0);

I would assume that this would move the distance move[0], then rotate the angle spin[0] and then the axis would be different for the next time round.

This is not so!

Reversing the two lines of code kinda works but if u rotate after translating the rotation point is all wrong!

Any helpful advice would be superb!

Regards,

Steve.

Maybe this will work:

glRotatef(0,1,0,spin[0]);
glTranslatef(0,0,move[0]);
glRotatef(0,1,0,-spin[0]);

Sorry, I switched the rotate parameters by accident.

glRotatef(spin[0],0,1,0);
glTranslatef(0,0,move[0]);
glRotatef(-spin[0],0,1,0);

glTranslatef(0,0,move[0]);
glRotatef(spin[0],0,1,0);
drawrobot();

This code moves your the origin of your local coordinatesystem to worldcoordinates (0,0,move[0]) and then rotates in this new coordinatesystem around the Y axis with an angle spin[0].
So the origin of your local coordinatesystem (that’s where you draw) is always located on the Z-axis of your world and your robot can’t leave the Z-axis.

If you want your robot to move in the XZ plane of your world using polar-coordinates (move[0],spin[0]) then indeed you should first rotate your local coordinatesystem around its Y axis and then move along the new Z-axis (wich does no longer coincide your world Z-axis).

glRotatef(spin[0],0,1,0);
glTranslatef(0,0,move[0]);
drawrobot();

When you talk about move around the screen, do you mean like pacman in a maze top view or more like in a 3D shooter?

It’s got to move around a plane - at the moment the camera’s fixed but I intend to aler that soon.

Using the solution:

glRotatef(spin[0],0,1,0);
glTranslatef(0,0,move[0]);
drawrobot();

I can turn, move forwards, but then if I turn again the robot rotates around the original point - not it’s current postion.

I need the spin to be the angle that it moves and the move to be the distance forward it goes. The robot should be able to turn left, turn right and move forwards.

You can do something like:

glRotatef(spin[0],0,1,0); // rotate robot around its Y
glTranslatef(0,0,move[0]); // move forward
glRotatef(-spin[0],0,1,0); // rotate robot back (it has its original orientation now)
glRotatef(angle,0,1,0); //give the robot the orientation you want
drawrobot();

you can combine angle-spin[0] to eliminate one rotation.

That doesn’t work either!

If you could possibly have time to see if you can see what the problem is it would help me big time!

Heres the code:

/* Coursework 1 for CM303 “Principles of Computer Graphics” */

/* Written by Stephen Lowe 1/11/03 */

#include <GL/glut.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

#define PI_ 3.14159265358979323846
static GLfloat spin[]={0,0,0},elbow1[]={0,-25,0},shoulder1[]={0,0},elbow2[]={0,25,0},shoulder2[]={0,0},wheel1[]={0,0};
static GLint fingers1=0,fingers2=0;
static GLfloat move[]={0,0};
/* Vertices to draw a hexagonal cylinder*/
GLfloat vertices[][3] = {{1,-1.5,0},{0.5,-1.5,-1},
{-0.5,-1.5,-1}, {-1,-1.5,0}, {-0.5,-1.5,1}, {0.5,-1.5,1},
{1,1.5,0}, {0.5,1.5,-1}, {-0.5,1.5,-1},{-1,1.5,0},
{-0.5,1.5,1}, {0.5,1.5,1}};
void sphere(void){
glPushMatrix();
glutSolidSphere(1, 30, 30);
glPopMatrix();
}
void cube(void){
glPushMatrix();
glutSolidCube(2);
glPopMatrix();
}

void lights(float x,float y, float z){
GLfloat pos[4] = {0.0, 0.0, 0.0, 1.0};
GLfloat ld1[] = {1., 1., 1., 1.};
GLfloat ls1[] = {1., 1., 1., 1.};
pos[0] = x;
pos[1] = y;
pos[2] = z;
glLightfv(GL_LIGHT1, GL_POSITION, pos);
glLightfv(GL_LIGHT1, GL_SPECULAR, ls1);
glLightfv(GL_LIGHT1, GL_DIFFUSE, ld1);
glEnable(GL_LIGHT1);
}

float MIN(float a, float b, float c){
if((a <= b) && (a <= c)) return a;
if((b < a) && (b < c)) return b;
if((c < b) && (c < a)) return c;
return a;
}

float MAX(float a, float b, float c){
if((a >= b) && (a >= c)) return a;
if((b > a) && (b > c)) return b;
if((c > b) && (c > a)) return c;
return a;
}

void RGBtoHSV( float r, float g, float b, float *h, float *s, float *v ) {
float min, max, delta;
min = MIN( r, g, b );
max = MAX( r, g, b );
*v = max; // v
delta = max - min;
if( max != 0 )
*s = delta / max; // s
else {
// r = g = b = 0 // s = 0, v is undefined
*s = 0;
*h = -1;
return;
}
if( r == max )
*h = ( g - b ) / delta; // between yellow & magenta
else if( g == max )
*h = 2 + ( b - r ) / delta; // between cyan & yellow
else
*h = 4 + ( r - g ) / delta; // between magenta & cyan
*h *= 60; // degrees
if( *h < 0 )
*h += 360;
}
// alows v > 1, and scales rgb accordingly
void HSVtoRGB( float *r, float *g, float *b, float h, float s, float v ) {
int i;
float f, p, q, t, sc;
if(v > 1.)
v = 1.;
sc = v;
if( s == 0 ) { // achromatic (grey)
*r = *g = *b = v;
return;
}
h /= 60; // sector 0 to 5
i = floor( h );
f = h - i; // factorial part of h
p = v * ( 1 - s );
q = v * ( 1 - s * f );
t = v * ( 1 - s * ( 1 - f ) );
switch( i ) {
case 0:
*r = v;
*g = t;
*b = p;
break;
case 1:
*r = q;
*g = v;
*b = p;
break;
case 2:
*r = p;
*g = v;
*b = t;
break;
case 3:
*r = p;
*g = q;
*b = v;
break;
case 4:
*r = t;
*g = p;
*b = v;
break;
default: // case 5:
*r = v;
*g = p;
*b = q;
break;
}
*r *= sc;
g = sc;
b = sc;
}
void drawRobot(){
glPushMatrix();
glScalef(0.5,0.5,0.5);
glPushMatrix();
//mColor(200., 1, 1, 1);
glTranslatef(0,1.9,0);
glScalef(0.5,0.5,0.5);
glutSolidSphere(1,15,15);
glPopMatrix();
glPushMatrix();
//mColor(10, 1, 0.5, 1);
glRotatef(90,1,0,0);
glTranslatef(0,0,-0.8);
gluCylinder(gluNewQuadric(),0.8,0.8,2,20,20);
glutSolidSphere(0.8,15,15);
glTranslatef(0,0,2);
gluDisk(gluNewQuadric(),0,0.8,20,20);
glPopMatrix();
glPushMatrix();
glTranslatef(-0.9,-0.95,0);
glRotatef(90,0,1,0);
glRotatef(wheel1[0],0,0,1);
glutSolidTorus(0.25,0.25,10,10);
glPopMatrix();
glPushMatrix();
glTranslatef(0.9,-0.95,0);
glRotatef(90,0,1,0);
glRotatef(wheel1[1],0,0,1);
glutSolidTorus(0.25,0.25,10,10);
glPopMatrix();
glPushMatrix();
glTranslatef(0.85,0.95,0);
glRotatef(45,0,1,0);
glRotatef(45,1,0,0);
glRotatef(shoulder1[0],1,0,0);
glRotatef(shoulder1[1],0,1,0);
glutSolidSphere(0.2,15,15);
gluCylinder(gluNewQuadric(),0.2,0.1,1,20,20);
glPushMatrix();
glTranslatef(0,0,1);
glRotatef(elbow1[0],1,0,0);
glRotatef(elbow1[1],0,1,0);
glRotatef(elbow1[2],0,0,1);
glutSolidSphere(0.1,15,15);
gluCylinder(gluNewQuadric(),0.1,0.08,0.5,20,20);
glPushMatrix();
glTranslatef(0,0,0.5);
glutSolidSphere(0.08 ,15,15);
glRotatef(25,0,1,0);
glRotatef(fingers1,0,1,0);
gluCylinder(gluNewQuadric(),0.05,0.05,0.35,20,20);
glTranslatef(0,0,0.35);
glutSolidSphere(0.05 ,15,15);
glPopMatrix();
glPushMatrix();
glTranslatef(0,0,0.5);
glRotatef(-25,0,1,0);
glRotatef(-fingers1,0,1,0);
gluCylinder(gluNewQuadric(),0.05,0.05,0.35,20,20);
glTranslatef(0,0,0.35);
glutSolidSphere(0.05 ,15,15);
glPopMatrix();
glPopMatrix();
glPopMatrix();
glPushMatrix();
glTranslatef(-0.85,0.95,0);
glRotatef(-45,0,1,0);
glRotatef(45,1,0,0);
glRotatef(shoulder2[0],1,0,0);
glRotatef(shoulder2[1],0,1,0);
glutSolidSphere(0.2,15,15);
gluCylinder(gluNewQuadric(),0.2,0.1,1,20,20);
glPushMatrix();
glTranslatef(0,0,1);
glRotatef(elbow2[0],1,0,0);
glRotatef(elbow2[1],0,1,0);
glRotatef(elbow2[2],0,0,1);
glutSolidSphere(0.1,15,15);
gluCylinder(gluNewQuadric(),0.1,0.08,0.5,20,20);
glPushMatrix();
glTranslatef(0,0,0.5);
glutSolidSphere(0.08 ,15,15);
glRotatef(25,0,1,0);
glRotatef(fingers2,0,1,0);
gluCylinder(gluNewQuadric(),0.05,0.05,0.35,20,20);
glTranslatef(0,0,0.35);
glutSolidSphere(0.05 ,15,15);
glPopMatrix();
glPushMatrix();
glTranslatef(0,0,0.5);
glRotatef(-25,0,1,0);
glRotatef(-fingers2,0,1,0);
gluCylinder(gluNewQuadric(),0.05,0.05,0.35,20,20);
glTranslatef(0,0,0.35);
glutSolidSphere(0.05 ,15,15);
glPopMatrix();
glPopMatrix();
glPopMatrix();
glPopMatrix();
}
void mColor(float H, float S, float V, float mix){
float r, g, b;
float amb = 0.2;
float mat[4] ;
HSVtoRGB( &r, &g, &b, H, S, V );
mat[0] = r * amb;
mat[1] = g
amb;
mat[2] = b
amb;
mat[3] = 1.0;
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat);
mat[0] = r * mix;
mat[1] = g * mix;
mat[2] = b * mix;
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat);
mat[0] = r
(1. - mix);
mat[1] = g
(1. - mix);
mat[2] = b * (1. - mix);;
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.6 * 128.0);

}

void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glEnable(GL_LIGHTING);
glColor3f(0.5,0.5,0.5);
lights(-5, 5, 5);
glTranslatef(0,0,10);
glPushMatrix();
glScalef(0.2,0.2,0.2);
glTranslatef(-1,-1,2);
sphere();
glPopMatrix();
glPushMatrix();
glRotatef(spin[0],0,1,0);
glTranslatef(0,0,move[0]);
glRotatef(-spin[0],0,1,0);
//glRotatef(25,0,1,0);
drawRobot();
glLoadIdentity();
glPopMatrix();
glDisable(GL_LIGHTING);
glutSwapBuffers();
glutPostRedisplay();
}

void myReshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0,w/h,0.2,4);
if (w <= h)
glOrtho(-2.0, 2.0, -2.0 * (GLfloat) h / (GLfloat) w,
2.0 * (GLfloat) h / (GLfloat) w, -10.0, 10.0);
else
glOrtho(-2.0 * (GLfloat) w / (GLfloat) h,
2.0 * (GLfloat) w / (GLfloat) h, -2.0, 2.0, -10.0, 10.0);
glMatrixMode(GL_MODELVIEW);
}

/* Rotate about x-axis when “x” typed; rotate about y-axis
when “y” typed; rotate about z-axis when “z” typed;
when “a”, “b”, “c”, or “d” typed relavant part of coursework shown */
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case ‘f’:
if(elbow1[1]>-90)
elbow1[1]-=4;
break;
case ‘F’:
if(elbow1[1]<0)
elbow1[1]+=4;
break;
case ‘s’:
elbow1[2]-=4;
break;
case ‘S’:
elbow1[2]+=4;
break;
case ‘l’:
if(shoulder1[0]>=-90)
shoulder1[0]-=4;
break;
case ‘L’:
if(shoulder1[0]<0)
shoulder1[0]+=4;
break;
case ‘p’:
if(shoulder1[1]>=-30)
shoulder1[1]-=4;
break;
case ‘P’:
if(shoulder1[1]<30)
shoulder1[1]+=4;
break;
case ‘m’:
if(fingers1>=-10)
fingers1-=4;
break;
case ‘M’:
if(fingers1<40)
fingers1+=4;
break;
case ‘d’:
if(elbow2[1]<90)
elbow2[1]+=4;
break;
case ‘D’:
if(elbow2[1]>0)
elbow2[1]-=4;
break;
case ‘a’:
elbow2[2]-=4;
break;
case ‘A’:
elbow2[2]+=4;
break;
case ‘k’:
if(shoulder2[0]>=-90)
shoulder2[0]-=4;
break;
case ‘K’:
if(shoulder2[0]<0)
shoulder2[0]+=4;
break;
case ‘o’:
if(shoulder2[1]<30)
shoulder2[1]+=4;
break;
case ‘O’:
if(shoulder2[1]>=-30)
shoulder2[1]-=4;
break;
case ‘n’:
if(fingers2>=-10)
fingers2-=4;
break;
case ‘N’:
if(fingers2<40)
fingers2+=4;
break;
case ‘v’:
spin[0]-=4;
wheel1[0]-=4;
wheel1[1]+=4;
break;
case ‘V’:
spin[0]+=4;
wheel1[0]+=4;
wheel1[1]-=4;
break;
case ‘b’:
move[0]+=0.1;
wheel1[0]+=6;
wheel1[1]+=6;
break;
case ‘B’:
move[0]-=0.1;
wheel1[0]-=6;
wheel1[1]-=6;
break;
case ‘q’:
case ‘Q’:
exit(0);
break;
case 27:
exit(0);
break;
}
}
main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutCreateWindow(“CM303 Coursework 2 - Robots”);
glutReshapeFunc(myReshape);
glutDisplayFunc(display);
glutIdleFunc(display);
glutKeyboardFunc(keyboard);
glEnable(GL_DEPTH_TEST);
glutMainLoop();
}

Your robot is following some route:
go a little forward, turn a little left, go a little forward,…

you have only move and spin, so you only know “the robot turned M times, en was going forward N times” but you don’t know the order. that means you cant say where it is.
(To position a robot in 2Dspace you should keep at least 3 vars)

You could calculate the positionchange (X,Z)relative to the startingpoint each time the robot moves and the orientation it is in. Calculating the orientation is simple just adding all rotations. The positionchange depends on its orientation.

case ‘v’:
spin[0]-=4.0;
wheel1[0]-=4;
wheel1[1]+=4;
break;
case ‘V’:
spin[0]+=4.0;
wheel1[0]+=4;
wheel1[1]-=4;
break;
case ‘b’:
move[2]+=0.1cos(3.141592spin[0]/180); // Z-coordinate relative to startpoint
move[0]+=0.1sin(3.141592spin[0]/180); // X-Coordinate relative to startpoint
wheel1[0]+=6;
wheel1[1]+=6;
break;
case ‘B’:
move[2]-=0.1cos(3.141592spin[0]/180); // Z-coordinate relative to startpoint
move[0]-=0.1sin(3.141592spin[0]/180); // X-Coordinate relative to startpoint
wheel1[0]-=6;
wheel1[1]-=6;

So when keeping this information, you just have to translate your robot to the new position, and then rotate it to the right angle.

glTranslatef(move[0],0,move[2]); // Move (X,Z)
glRotatef(spin[0],0,1,0); // rotate

[This message has been edited by croce (edited 11-27-2003).]

This works!

There is a problem though - if you turn the robot so that it faces the screen and then move towards the screen it gets to a point and then crashes my computer!

Is this a problem with the code?

Yes!
If your computer crash’s, I am guessing that you have a variable that is being accessed passed the area reserved for it.

Check your code and look for where a array is going beyond its limit.

ie… int parts[10]---- then your write to parts[12]

Originally posted by SteveLowe:
[b]This works!

There is a problem though - if you turn the robot so that it faces the screen and then move towards the screen it gets to a point and then crashes my computer!

Is this a problem with the code?[/b]

It actually only crashes my laptop - it works fine on my desktop!