// ************************************************************* // The Robotics Institute // Carnegie Mellon University // Copyright (C) 2000 by RI. // All Rights Reserved. // // File: robot.cpp // Project: PalmPilot Robot source code (Advanced project) // Author: Greg Reshko // Last modified: 4/03/2000 // Program: // Implementation of Robot class defined in 'robot.h' // ************************************************************* // Calculates distance using Power Regression y=a*x^b // returns value in cm ranging from 10 to 80 int Robot::Sensor_To_Range(double x) { double a=2141.72055; double b=-1.078867; int y=100; if ( (x>0) && (x<250) ) { y = a*pow(x,b); } if (y<10) y=10; if (y>100) y=100; return y; } // Calculates servo value using Cubic Regression y=a*x^3+b*x^2+c*x+d // Converts velocity in rad per second to servo value (0-255) // vel can only be [-6,6] rad/sec // x can only be [-1,1] rev/sec int Robot::Vel_To_Value(double vel) { double x; x = vel / PI / 2; // convert rad/sec to rev/sec if ( (vel>-6) && (vel<6) ) return (39.8053*x*x*x - 12.6083*x*x + 22.1197*x + 128.4262); else return 0; } // default constructor Robot::Robot() { Err error; // find and open MathLib library error = SysLibFind(MathLibName, &MathLibRef); if (error) error = SysLibLoad(LibType, MathLibCreator, &MathLibRef); ErrFatalDisplayIf(error, "Can't find MathLib"); error = MathLibOpen(MathLibRef, MathLibVersion); ErrFatalDisplayIf(error, "Can't open MathLib"); Stop(); // stop all motors } // default destructor Robot::~Robot() { Err error; // close MathLib library UInt usecount; error = MathLibClose(MathLibRef, &usecount); ErrFatalDisplayIf(error, "Can't close MathLib"); if (usecount == 0) SysLibRemove(MathLibRef); Stop(); // stop all motors } void Robot::Servo(int servo_number, int velocity) { board.Tx("SV", servo_number); board.Tx("M", velocity); } // drive 3 servo-motors void Robot::Drive(int s1_vel, int s2_vel, int s3_vel) { Servo(1, s1_vel); Servo(2, s2_vel); Servo(3, s3_vel); } // Drives robot in a given direction vector V with given angular // velocity omega. // r - wheel radius in meters // b - wheel baseline in meters // ||V|| must be less than ~0.1 ! void Robot::Vector_Drive(vector V, double omega) { vector F1(-1.000,0.000), F2(0.500,-0.866), F3(0.866,0.500); double omega1, omega2, omega3, b=0.090, r=0.020, h=0; omega1 = ( F1*V + b*omega ) / r; // F1*V is overloaded dot product omega2 = ( F2*V + b*omega ) / r; omega3 = ( F3*V + b*omega ) / r; // makes sure that given path is physically possible if ( (omega1>6) || (omega2>6) || (omega3>6) || (omega1<-6) || (omega2<-6) || (omega3<-6) ) Message("Vectors: ERROR!"); else Drive(Vel_To_Value(omega1),Vel_To_Value(omega2),Vel_To_Value(omega3)); } // Display string (outputs it to Message Field) void Robot::Message(const Char* str) { FormPtr frm = FrmGetActiveForm(); FrmCopyLabel(frm, Form1MesLabel, " "); FrmCopyLabel(frm, Form1MesLabel, str); } // Displays number (outputs it to Message Field) void Robot::Message(int number) { FormPtr frm = FrmGetActiveForm(); char numbertxt[]=" "; FrmCopyLabel(frm, Form1MesLabel, numbertxt); StrIToA(numbertxt, number); FrmCopyLabel(frm, Form1MesLabel, numbertxt); } // stop each servo motor void Robot::Stop(void) { Servo(1,0); Servo(2,0); Servo(3,0); } // reads and returns distance in cm from IR sensor to an obstacle int Robot::IRDist(int ir_number) { int value=0, distance; char incoming[]="999"; board.Tx("AD", ir_number); board.Rc(incoming); // buffer correction -- replace all ASCII non-numbers with spaces for (int l=0; l<=2; l++) if ( incoming[l] == 10 ) incoming[l]=' '; incoming[3] = '\0'; if (incoming[0] != '1') // two digit number cut-off incoming[2] = '\0'; value = StrAToI(incoming); distance = Sensor_To_Range(value); return distance; } // Pauses application for specified number of ticks // Can be interrupted by penDown event // If *interrupt was provided: // Sets *interrupt to 1 if it was interrupted by penDown // Sets *interrupt to 0 if delay ended with no interrupts void Robot::Wait(int delay_ticks, int *interrupt) { ULong start_time; EventPtr quit_event; start_time = TimGetTicks(); while ( TimGetTicks() < (start_time + delay_ticks)) { EvtGetEvent(quit_event, 1); // get event using 1ms timeout if (quit_event->eType == penDownEvent) { // stop if screen was touched anywhere if (interrupt != NULL) { *interrupt = 1; } break; }} if (interrupt != NULL) { *interrupt = 0; } }