//## begin module%1.4%.codegen_version preserve=yes // Read the documentation to learn more about C++ code generator // versioning. //## end module%1.4%.codegen_version //## begin module%3D86D3F4029E.cm preserve=no // %X% %Q% %Z% %W% //## end module%3D86D3F4029E.cm //## begin module%3D86D3F4029E.cp preserve=no //## end module%3D86D3F4029E.cp //## Module: Drive%3D86D3F4029E; Pseudo Package body //## Source file: C:\Program Files\Rational\Rose\C++\source\Drive.cpp //## begin module%3D86D3F4029E.additionalIncludes preserve=no //## end module%3D86D3F4029E.additionalIncludes //## begin module%3D86D3F4029E.includes preserve=yes #include "math.h" //## end module%3D86D3F4029E.includes // Drive #include "Drive.h" //## begin module%3D86D3F4029E.additionalDeclarations preserve=yes //## end module%3D86D3F4029E.additionalDeclarations // Class Drive //## begin Drive::aDrive%3D9AA0AE0186.attr preserve=no private: static Drive {U} Drive Drive::drives[NUMBER_OF_ROBOTS]; //## end Drive::aDrive%3D9AA0AE0186.attr Drive::Drive() //## begin Drive::Drive%3D86D3F4029E_const.hasinit preserve=no : standardSpeed(0.18), standardOmega(35.0) //## end Drive::Drive%3D86D3F4029E_const.hasinit //## begin Drive::Drive%3D86D3F4029E_const.initialization preserve=yes //## end Drive::Drive%3D86D3F4029E_const.initialization { //## begin Drive::Drive%3D86D3F4029E_const.body preserve=yes //to run the program on the EyeSim simulator the initialization must not take place //in the constructor //so we have to declare the method as public and call it in main before we start //the program //if running the program on real robots the initialization must be done in the //constructors (otherwise the camera initialization doesn't work, for example //(for whatever reason) // initialize(); //## end Drive::Drive%3D86D3F4029E_const.body } Drive::~Drive() { //## begin Drive::~Drive%3D86D3F4029E_dest.body preserve=yes release(); //## end Drive::~Drive%3D86D3F4029E_dest.body } //## Other Operations (implementation) Drive* Drive::getDrive () { //## begin Drive::getDrive%3D9AA0D003AC.body preserve=yes return &drives[OSMachineID()]; //## end Drive::getDrive%3D9AA0D003AC.body } void Drive::setStandardSpeed (double speed, double omega) { //## begin Drive::setStandardSpeed%3D9294AB02F8.body preserve=yes standardSpeed = speed; standardOmega = omega; //## end Drive::setStandardSpeed%3D9294AB02F8.body } void Drive::setPosition (double x, double y, double phi) { //## begin Drive::setPosition%3D9294FF03C0.body preserve=yes VWSetPosition(vwDriveHandle, x*1000, y*1000, 2*PI*phi/360.0); //diff. sim - physical robots //## end Drive::setPosition%3D9294FF03C0.body } void Drive::getPosition (double& x, double& y, double& phi) { //## begin Drive::getPosition%3D929543012C.body preserve=yes PositionType position; VWGetPosition(vwDriveHandle, &position); x = position.x; y = position.y; phi = 180.0*(position.phi)/PI; //## end Drive::getPosition%3D929543012C.body } void Drive::driveWith (double speed, double omega) { //## begin Drive::driveWith%3D92957102F8.body preserve=yes VWSetSpeed(vwDriveHandle, speed, 2.0*PI*omega/360.0); //conversion from degree/second to rad/second if (speed == 0.0 && omega == 0.0) { stalled(); //if the robot is stopped we called stalled() here to reset the counter in the stalled method, see Drive::stalled } //## end Drive::driveWith%3D92957102F8.body } void Drive::drive (double distance) { //## begin Drive::drive%3D9295AA0370.body preserve=yes VWDriveStraight(vwDriveHandle, distance, standardSpeed); //## end Drive::drive%3D9295AA0370.body } void Drive::driveCircle (double radius, double angle) { //## begin Drive::driveCircle%3D92960A037A.body preserve=yes driveCurve(2*PI*radius*fabs(angle)/360.0, angle); //abs(angle) needed so that orientation of angle does not change orientation of movement //## end Drive::driveCircle%3D92960A037A.body } bool Drive::driveTo (double x, double y) { //## begin Drive::driveTo%3D9295CC0118.body preserve=yes //NOT IMPLEMENTED YET, DO NOT USE return false; //## end Drive::driveTo%3D9295CC0118.body } bool Drive::driveTo (double x, double y, double phi) { //## begin Drive::driveTo%3D9295EE0262.body preserve=yes //NOT IMPLEMENTED YET, DO NOT USE return false; //## end Drive::driveTo%3D9295EE0262.body } void Drive::turnRight (double angle) { //## begin Drive::turnRight%3D9296430320.body preserve=yes turnLeft(-angle); //## end Drive::turnRight%3D9296430320.body } void Drive::turnLeft (double angle) { //## begin Drive::turnLeft%3D92965702A8.body preserve=yes VWDriveTurn(vwDriveHandle, +2.0*PI*angle/360.0, 2.0*PI*standardOmega/360.0); //## end Drive::turnLeft%3D92965702A8.body } void Drive::turnTo (double angle) { //## begin Drive::turnTo%3D929658000A.body preserve=yes /* NOT IMPLEMENTED YET, DO NOT USE //does the EyeBot return angles from -180.0 to 179.9?? //0 .. 179.9 means to the left //-0.1 .. -180.0 means to the right double x; double y; double phi; getPosition(x, y, phi); double difference = angle - phi; while (difference >= 180.0) difference-=360.0; while (difference < -180.0) difference+=360.0; turn(difference); */ //## end Drive::turnTo%3D929658000A.body } bool Drive::done () { //## begin Drive::done%3D9296680258.body preserve=yes return (VWDriveDone(vwDriveHandle)==1?true:false); //## end Drive::done%3D9296680258.body } void Drive::wait () { //## begin Drive::wait%3D92966D017C.body preserve=yes VWDriveWait(vwDriveHandle); //## end Drive::wait%3D92966D017C.body } bool Drive::stalled () { //## begin Drive::stalled%3D92967101B8.body preserve=yes return (VWStalled(vwDriveHandle)==1?true:false); //diff. sim. - physical robots //## end Drive::stalled%3D92967101B8.body } bool Drive::initialize () { //## begin Drive::initialize%3D9292E100F0.body preserve=yes if (!(vwDriveHandle = VWInit(VW_DRIVE, 1))) //1 means maximum accuracy { LCDPutString("Drive init. error!\n"); OSPanic(""); //put that into calling function and return false here?? } driveWith(0,0); //stop drive first VWStartControl(vwDriveHandle, 7.0, 0.3, 7.0, 0.1); //starts PI-controller using given parameters. See EyeBot documentation for explanation of parameters return true; //## end Drive::initialize%3D9292E100F0.body } bool Drive::release () { //## begin Drive::release%3D9292E10122.body preserve=yes VWRelease(vwDriveHandle); return true; //## end Drive::release%3D9292E10122.body } // Additional Declarations //## begin Drive%3D86D3F4029E.declarations preserve=yes double Drive::getRotationAngleTo(double pointX, double pointY) { double x, y, phi; getPosition(x,y,phi); return getRotationAngle(x,y,pointX,pointY,phi); } double Drive::getRotationAngle(double baseX, double baseY, double pointX, double pointY, double phi) { double diffX = pointX-baseX; double diffY = pointY-baseY; double diffPhi; diffPhi = 360.0 * atan2(diffY, diffX) / (2 * PI); // adjusted by the current robot angle diffPhi -= phi; // angle always between (-180..180] while (diffPhi > 180.0) diffPhi -= 360.0; while (diffPhi <= -180.0) diffPhi += 360.0; return diffPhi; } void Drive::driveCurveTo(double x, double y) { double robotX, robotY, phi; getPosition(robotX, robotY, phi); // angle between robot and point, adjusted by current robot orientation double rotationAngleToPoint = getRotationAngle(robotX, robotY, x, y, phi); // distance to point in a straight line double distanceToPoint = sqrt((x-robotX)*(x-robotX)+(y-robotY)*(y-robotY)); double driveDistance = 0.0; if (fabs(rotationAngleToPoint) == 0.0) driveDistance = distanceToPoint; //we drive straight else if (fabs(rotationAngleToPoint) >= 135.0) //doesn't make sense to drive in a curve to an object that lies right behind us, so we just turn to that point and drive straight { turn(rotationAngleToPoint); while(!done() && !stalled()) { } if (stalled()) //but now we are missing the spot??? stop(); rotationAngleToPoint = 0.0; driveDistance = distanceToPoint; //we drive straight } else driveDistance = distanceToPoint * (2.0*PI*rotationAngleToPoint/360.0) / sin((2.0*PI*rotationAngleToPoint/360.0)); //we drive in a curve to the passed point. Here we calculate the distance we have to drive on the curve driveCurve(driveDistance, 2.0 * rotationAngleToPoint); } void Drive::turn (double angle) { turnLeft(angle); } void Drive::driveCurve (double distanceOnCurve, double deltaPhi) { VWDriveCurve(vwDriveHandle, distanceOnCurve, 2.0*PI*deltaPhi/360.0, standardSpeed); } void Drive::stop () { driveWith(0, 0); } void Drive::driveStraight () { driveWith(standardSpeed, 0); } void Drive::backup () { driveWith(-standardSpeed, 0); } double Drive::distanceTo(double x, double y) { double currentPositionX; double currentPositionY; double phi; getPosition(currentPositionX, currentPositionY, phi); return sqrt((currentPositionX-x)*(currentPositionX-x)+(currentPositionY-y)*(currentPositionY-y)); } void Drive::turnRight () { driveWith(0.0, - standardOmega); } void Drive::turnLeft () { driveWith(0.0, + standardOmega); } bool Drive::commandCompleted() { while(!done() && !stalled()) { OSReschedule(); } if (stalled()) { stop(); return false; } else return true; } void Drive::local2global(double robotX, double robotY, double robotPhi, double localX, double localY, double& globalX, double& globalY) { globalX = robotX + cos(2*PI*robotPhi/360.0)*localX + sin(2*PI*robotPhi/360.0)*localY; globalY = robotY + cos(2*PI*robotPhi/360.0)*localY + sin(2*PI*robotPhi/360.0)*localX; } //## end Drive%3D86D3F4029E.declarations //## begin module%3D86D3F4029E.epilog preserve=yes //## end module%3D86D3F4029E.epilog