#include <angles.h>
#include <solver.h>
#include <nav.h>
unsigned char IR_Threshold[6];
int Nav_MovingForwards;
int Nav_Busy;
int Nav_WallOnLeft,Nav_WallOnRight;
int IR_FrontCentre,IR_RearCentre;
Path *Nav_CurPath;
Exits Nav_Exits;
Exits Nav_CurExits;
Dir Nav_CurDir;
void navmain()
{
Nav_MovingForwards = 1;
Nav_CurDir = DIR_N;
Nav_Busy=0;
Nav_CurPath=NULL;
Nav_Exits=0;
SetMotorSpeed(0,0);
IR_FrontCentre=0xCF;
IR_RearCentre=0xCF;
while (1) {
while (!Nav_CurPath)
idle();
IR_on();
Nav_Busy=1;
Nav_ExecPath();
IR_off();
Nav_Busy=0;
}
}
Exits MC_Move(Path *P) {
Nav_CurPath=Path_COPY(P);
printf("MC_Move Called.\n",0);
Print(P);
while (Nav_Busy)
idle();
while (Nav_CurPath)
idle();
return Nav_Exits;
}
void Nav_ExecPath() {
int MoveCount;
int CurMove,cur_x,cur_y;
int MoveLen,MoveDir;
int i;
Move M;
MoveCount=Path_NumberOfMoves(Nav_CurPath);
cur_x=X*NAV_CELL_SIZE;
cur_y=Y*NAV_CELL_SIZE;
for (CurMove=0;CurMove<MoveCount;CurMove++) {
int dx,dy;
int dx1,dy1;
M = Path_MoveNo(Nav_CurPath,CurMove);
MoveDir=M&MOVE_DIRMASK;
MoveLen=M&MOVE_LENMASK;
if ((Nav_CurDir^DIR_REVERSE)==(Dir)MoveDir)
Nav_MovingForwards=!Nav_MovingForwards;
Nav_CurDir=(Dir)MoveDir;
dx=DX[DIRNUM(M)]*NAV_CELL_SIZE;
dy=DY[DIRNUM(M)]*NAV_CELL_SIZE;
for (i=1;i<MoveLen;i++) {
Nav_MoveTo(cur_x+(dx/2),cur_y+(dy/2));
cur_x+=dx;
cur_y+=dy;
Nav_MoveTo(cur_x,cur_y);
Nav_ErrorCorrect();
}
Nav_MoveTo(cur_x+(dx/2),cur_y+(dy/2));
Nav_CurExits=Nav_GetExits();
Nav_ErrorCorrect();
if (CurMove==(MoveCount-1)) {
Nav_Exits=Nav_CurExits;
Path_KILL(&Nav_CurPath);
}
dx1=DX[DIRNUM(M)]*NAV_CELL_STOPPOS;
dy1=DY[DIRNUM(M)]*NAV_CELL_STOPPOS;
Nav_MoveTo(cur_x+dx1,cur_y+dy1);
cur_x+=dx;
cur_y+=dy;
}
SetMotorSpeed(0,0);
}
Exits Nav_GetExits() {
int Front,Left,Right;
if (Nav_MovingForwards) {
Front=Analog(0)>IR_Threshold[0];
Left=Analog(1)>IR_Threshold[1];
Right=Analog(2)>IR_Threshold[2];
} else {
Front=Analog(3)>IR_Threshold[3];
Left=Analog(5)>IR_Threshold[5];
Right=Analog(4)>IR_Threshold[4];
}
Nav_WallOnLeft=!Left;
Nav_WallOnRight=!Right;
switch (Nav_CurDir) {
case DIR_N:
return EXIT_S+(Front?EXIT_N:0)+(Left?EXIT_W:0)+(Right?EXIT_E:0);
case DIR_S:
return EXIT_N+(Front?EXIT_S:0)+(Left?EXIT_E:0)+(Right?EXIT_W:0);
case DIR_E:
return EXIT_W+(Front?EXIT_E:0)+(Left?EXIT_N:0)+(Right?EXIT_S:0);
case DIR_W:
return EXIT_E+(Front?EXIT_W:0)+(Left?EXIT_S:0)+(Right?EXIT_N:0);
}
return 0;
}
void Nav_ErrorCorrect() {
if (Nav_WallOnLeft&&Nav_WallOnRight) {
int Error,XError,YError,AngError;
int n1,n2;
if (Nav_MovingForwards) {
n1=Analog(1);
n2=Analog(2);
} else {
n1=Analog(5);
n2=Analog(4);
}
IR_FrontCentre=(IR_FrontCentre*14+n1+n2)/16;
Error=(n1-n2)/12;
XError=Error*(DY[DIRNUM(Nav_CurDir)]);
YError=Error*(-DX[DIRNUM(Nav_CurDir)]);
AngError=-Error;
OPT_Correct(XError,YError,AngError);
} else {
if (Nav_WallOnLeft) {
int Error,XError,YError,AngError;
int n1;
if (Nav_MovingForwards) {
n1=Analog(1);
Error=(n1-IR_FrontCentre)/10;
} else {
n1=Analog(5);
Error=(n1-IR_RearCentre)/10;
}
XError=Error*(DY[DIRNUM(Nav_CurDir)]);
YError=Error*(-DX[DIRNUM(Nav_CurDir)]);
AngError=-Error;
OPT_Correct(XError,YError,AngError);
}
if (Nav_WallOnRight) {
int Error,XError,YError,AngError;
int n1;
if (Nav_MovingForwards) {
n1=Analog(2);
Error=(IR_FrontCentre-n1)/10;
} else {
n1=Analog(4);
Error=(IR_RearCentre-n1)/10;
}
XError=Error*(DY[DIRNUM(Nav_CurDir)]);
YError=Error*(-DX[DIRNUM(Nav_CurDir)]);
AngError=-Error;
OPT_Correct(XError,YError,AngError);
}
}
}
void Nav_MoveTo(int x,int y) {
IR_on();
if (Nav_MovingForwards)
switch(Nav_CurDir) {
case DIR_N:
move_FWD_N(y,x);
break;
case DIR_E:
move_FWD_E(x,y);
break;
case DIR_W:
move_FWD_W(x,y);
break;
case DIR_S:
move_FWD_S(y,x);
break;
}
else
switch(Nav_CurDir)
{
case DIR_N:
move_REV_N(y,x);
break;
case DIR_E:
move_REV_E(x,y);
break;
case DIR_W:
move_REV_W(x,y);
break;
case DIR_S:
move_REV_S(y,x);
break;
}
}
void move_FWD_N(int dest_Y,int centre_X) {
int dif;
while (OPT_Y_Pos()<dest_Y) {
dif=sgn(OPT_X_Pos()-centre_X,SGN_COEFF);
dif+=DIST_COEFF*(OPT_X_Pos()-centre_X);
dif-=ANG_COEFF*Sin127(OPT_Angle());
SetMotorSpeed(400-dif,400+dif);
}
}
void move_FWD_E(int dest_X,int centre_Y) {
int dif;
while (OPT_X_Pos()<dest_X) {
dif=sgn(centre_Y-OPT_Y_Pos(),SGN_COEFF);
dif+=DIST_COEFF*(centre_Y-OPT_Y_Pos());
dif-=ANG_COEFF*Cos127(OPT_Angle());
SetMotorSpeed(400-dif,400+dif);
}
}
void move_FWD_S(int dest_Y,int centre_X) {
int dif;
while (OPT_Y_Pos()>dest_Y) {
dif=sgn(centre_X-OPT_X_Pos(),SGN_COEFF);
dif+=DIST_COEFF*(centre_X-OPT_X_Pos());
dif+=ANG_COEFF*Sin127(OPT_Angle());
SetMotorSpeed(400-dif,400+dif);
}
}
void move_FWD_W(int dest_X,int centre_Y) {
int dif;
while (OPT_X_Pos()>dest_X) {
dif=sgn(OPT_Y_Pos()-centre_Y,SGN_COEFF);
dif+=DIST_COEFF*(OPT_Y_Pos()-centre_Y);
dif+=ANG_COEFF*Cos127(OPT_Angle());
SetMotorSpeed(400-dif,400+dif);
}
}
void move_REV_N(int dest_Y,int centre_X) {
int dif;
while (OPT_Y_Pos()<dest_Y) {
dif=+sgn(OPT_X_Pos()-centre_X,SGN_COEFF);
dif+=DIST_COEFF*(OPT_X_Pos()-centre_X);
dif+=ANG_COEFF*Sin127(OPT_Angle());
SetMotorSpeed(-400-dif,-400+dif);
}
}
void move_REV_E(int dest_X,int centre_Y) {
int dif;
while (OPT_X_Pos()<dest_X) {
dif=sgn(centre_Y-OPT_Y_Pos(),SGN_COEFF);
dif+=DIST_COEFF*(centre_Y-OPT_Y_Pos());
dif+=ANG_COEFF*Cos127(OPT_Angle());
SetMotorSpeed(-400-dif,-400+dif);
}
}
void move_REV_S(int dest_Y,int centre_X) {
int dif;
while (OPT_Y_Pos()>dest_Y) {
dif=+sgn(centre_X-OPT_X_Pos(),SGN_COEFF);
dif+=DIST_COEFF*(centre_X-OPT_X_Pos());
dif-=ANG_COEFF*Sin127(OPT_Angle());
SetMotorSpeed(-400-dif,-400+dif);
}
}
void move_REV_W(int dest_X,int centre_Y) {
int dif;
while (OPT_X_Pos()>dest_X) {
dif=+sgn(OPT_Y_Pos()-centre_Y,SGN_COEFF);
dif+=DIST_COEFF*(OPT_Y_Pos()-centre_Y);
dif-=ANG_COEFF*Cos127(OPT_Angle());
SetMotorSpeed(-400-dif,-400+dif);
}
}