dpptuExample.cpp

Shows how to control the Directed Perceptions Pan-Tilt Unit.

This program lets you use the keyboard to control the DPPTU. It uses the same acceleration and slew rates for the pan and tilt axes.

Commands: _________________

UP,DOWN -- tilt up/down by one positional increment LEFT,RIGHT -- pan left/right by one positional increment SPACE -- perform reset calibration I -- initialize PTU to default settings <,> -- increase/decrease the posIncrement by 1 degree +,- -- increase/decrease the speed by 1 degree/sec A -- awaits the completion of last issued positional command R -- change pan/tilt movements to relative or absolute movements Z -- move pan and tilt axes to zero M -- Enter or Exit monitor mode H -- Halt all motion S -- print current variable values ESC -- quit

00001 #include "Aria.h"
00002 
00025 // If defined, use this computer serial port. If not defined, use first robot
00026 // aux. serial port.  Most robots have the DPPTU on COM2 if on Linux and COM4 on
00027 // Windows, if not equipped with other accessories which might require those
00028 // ports (e.g. GPS or Laser).
00029 #define SERIAL_PORT ArUtil::COM4
00030 
00031 /*
00032   This class is the core of this demo, it adds itself to the robot given
00033   as a user task, and contains key handler callbacks to control the PTU.
00034 */
00035 class KeyPTU
00036 {
00037 public:
00038   // constructor
00039   KeyPTU(ArRobot *robot);
00040   ~KeyPTU(void);
00041   
00042   void up(void);
00043   void down(void);
00044   void left(void);
00045   void right(void);
00046   void space(void);
00047   void i(void);
00048   void plus(void);
00049   void minus(void);
00050   void greater(void);
00051   void less(void);
00052   void question(void);
00053   void status(void);
00054   void a(void);
00055   void z(void);
00056   void m(void);
00057   void h(void);
00058   void r(void);
00059 
00060   // the callback function
00061   void drive(void);
00062 
00063 protected:
00064   int myPanValPTU;
00065   int myTiltValPTU;
00066 
00067   int myDesiredPanPos;
00068   int myDesiredTiltPos;
00069   int mySlew;
00070   int myPosIncrement;
00071   int mySlewIncrement;
00072 
00073   int posIncIncrement;
00074 
00075   bool myMonitor;
00076   bool myReset;
00077   bool myInit;
00078   bool myAbsolute;
00079 
00080   ArFunctorC<KeyPTU> myUpCB;
00081   ArFunctorC<KeyPTU> myDownCB;
00082   ArFunctorC<KeyPTU> myLeftCB;
00083   ArFunctorC<KeyPTU> myRightCB;
00084   ArFunctorC<KeyPTU> mySpaceCB;
00085   ArFunctorC<KeyPTU> myICB;
00086   ArFunctorC<KeyPTU> myPlusCB;
00087   ArFunctorC<KeyPTU> myMinusCB;
00088   ArFunctorC<KeyPTU> myGreaterCB;
00089   ArFunctorC<KeyPTU> myLessCB;
00090   ArFunctorC<KeyPTU> myQuestionCB;
00091   ArFunctorC<KeyPTU> mySCB;
00092   ArFunctorC<KeyPTU> myACB;
00093   ArFunctorC<KeyPTU> myZCB;
00094   ArFunctorC<KeyPTU> myMCB;
00095   ArFunctorC<KeyPTU> myHCB;
00096   ArFunctorC<KeyPTU> myRCB;
00097 
00098 
00099   // the PTU
00100   ArDPPTU myPTU;
00101   
00102 
00103   // whether the PTU has been inited or not
00104   bool myPTUInited;
00105   // pointer to the robot
00106   ArRobot *myRobot;
00107   // callback for the drive function
00108   ArFunctorC<KeyPTU> myDriveCB;
00109 
00110   ArSerialConnection *mySerialConnection;
00111 };
00112 
00113 /*
00114   Constructor, sets the robot pointer, and some initial values, also note the
00115   use of constructor chaining on myPTU and myDriveCB.
00116 */
00117 KeyPTU::KeyPTU(ArRobot *robot) :
00118   myUpCB(this, &KeyPTU::up),
00119   myDownCB(this, &KeyPTU::down),
00120   myLeftCB(this, &KeyPTU::left),
00121   myRightCB(this, &KeyPTU::right),
00122   mySpaceCB(this, &KeyPTU::space),
00123   myICB(this, &KeyPTU::i),
00124   myPlusCB(this, &KeyPTU::plus),
00125   myMinusCB(this, &KeyPTU::minus),
00126   myGreaterCB(this, &KeyPTU::greater),
00127   myLessCB(this, &KeyPTU::less),
00128   myQuestionCB(this, &KeyPTU::question),
00129   mySCB(this, &KeyPTU::status),
00130   myACB(this, &KeyPTU::a),
00131   myZCB(this, &KeyPTU::z),
00132   myMCB(this, &KeyPTU::m),
00133   myHCB(this, &KeyPTU::h),
00134   myRCB(this, &KeyPTU::r),
00135   myPTU(robot),
00136   myDriveCB(this, &KeyPTU::drive),
00137   mySerialConnection(NULL)
00138 {
00139 #ifdef SERIAL_PORT
00140   mySerialConnection = new ArSerialConnection;
00141   ArLog::log(ArLog::Normal, "dpptuExample: connecting to DPPTU over computer serial port %s.", SERIAL_PORT);
00142   if(mySerialConnection->open(SERIAL_PORT) != 0)
00143   {
00144     ArLog::log(ArLog::Terse, "dpptuExample: Error: Could not open computer serial port %s for DPPTU!", SERIAL_PORT);
00145     Aria::exit(5);
00146   }
00147   myPTU.setDeviceConnection(mySerialConnection);
00148 #endif
00149 
00150   // set the robot pointer and add the KeyPTU as user task
00151   ArKeyHandler *keyHandler;
00152   myRobot = robot;
00153   myRobot->addSensorInterpTask("KeyPTU", 50, &myDriveCB);
00154 
00155   if ((keyHandler = Aria::getKeyHandler()) == NULL)
00156   {
00157     keyHandler = new ArKeyHandler;
00158     Aria::setKeyHandler(keyHandler);
00159     myRobot->attachKeyHandler(keyHandler);
00160   }
00161 
00162   if (!keyHandler->addKeyHandler(ArKeyHandler::UP, &myUpCB))
00163     ArLog::log(ArLog::Terse, "The key handler already has a key for up, keydrive will not work correctly.");
00164   if (!keyHandler->addKeyHandler(ArKeyHandler::DOWN, &myDownCB))
00165     ArLog::log(ArLog::Terse, "The key handler already has a key for down, keydrive will not work correctly.");
00166   if (!keyHandler->addKeyHandler(ArKeyHandler::LEFT, &myLeftCB))
00167     ArLog::log(ArLog::Terse,  
00168 "The key handler already has a key for left, keydrive will not work correctly.");
00169   if (!keyHandler->addKeyHandler(ArKeyHandler::RIGHT, &myRightCB))
00170     ArLog::log(ArLog::Terse,  
00171 "The key handler already has a key for right, keydrive will not work correctly.");
00172   if (!keyHandler->addKeyHandler(ArKeyHandler::SPACE, &mySpaceCB))
00173     ArLog::log(ArLog::Terse,
00174 "The key handler already has a key for space, keydrive will not work correctly.");
00175   if (!keyHandler->addKeyHandler('i', &myICB))
00176     ArLog::log(ArLog::Terse,
00177 "The key handler already has a key for 'i', keydrive will not work correctly.");
00178   if (!keyHandler->addKeyHandler('+', &myPlusCB))
00179     ArLog::log(ArLog::Terse,
00180 "The key handler already has a key for '+', keydrive will not work correctly.");
00181   if (!keyHandler->addKeyHandler('-', &myMinusCB))
00182     ArLog::log(ArLog::Terse,
00183 "The key handler already has a key for '-', keydrive will not work correctly.");
00184   if (!keyHandler->addKeyHandler('>', &myGreaterCB))
00185     ArLog::log(ArLog::Terse,
00186 "The key handler already has a key for '>', keydrive will not work correctly.");
00187   if (!keyHandler->addKeyHandler('<', &myLessCB))
00188     ArLog::log(ArLog::Terse,
00189 "The key handler already has a key for '<', keydrive will not work correctly.");
00190   if (!keyHandler->addKeyHandler('?', &myQuestionCB))
00191     ArLog::log(ArLog::Terse,
00192 "The key handler already has a key for '?', keydrive will not work correctly.");
00193   if (!keyHandler->addKeyHandler('s', &mySCB))
00194     ArLog::log(ArLog::Terse,
00195 "The key handler already has a key for 'S', keydrive will not work correctly.");
00196   if (!keyHandler->addKeyHandler('a', &myACB))
00197     ArLog::log(ArLog::Terse,
00198 "The key handler already has a key for 'A', keydrive will not work correctly.");
00199   if (!keyHandler->addKeyHandler('z', &myZCB))
00200     ArLog::log(ArLog::Terse,
00201 "The key handler already has a key for 'Z', keydrive will not work correctly.");
00202   if (!keyHandler->addKeyHandler('m', &myMCB))
00203     ArLog::log(ArLog::Terse,
00204 "The key handler already has a key for 'M', keydrive will not work correctly.");
00205   if (!keyHandler->addKeyHandler('h', &myHCB))
00206     ArLog::log(ArLog::Terse,
00207 "The key handler already has a key for 'H', keydrive will not work correctly.");
00208   if (!keyHandler->addKeyHandler('r', &myRCB))
00209     ArLog::log(ArLog::Terse,
00210 "The key handler already has a key for 'R', keydrive will not work correctly.");
00211 
00212   // initialize some variables
00213   myReset = false;
00214   myInit = true;
00215   myDesiredPanPos = 0;
00216   myDesiredTiltPos = 0;
00217   myPosIncrement = 1;
00218   mySlewIncrement = 1;
00219   myPTUInited = false;
00220   posIncIncrement = 1;
00221   myMonitor = false;
00222 
00223 }
00224 
00225 KeyPTU::~KeyPTU() 
00226 {
00227   if(mySerialConnection)
00228   {
00229     myPTU.setDeviceConnection(NULL);
00230     delete mySerialConnection;
00231   }
00232 }
00233 
00234 
00235 
00236 void KeyPTU::left(void)
00237 {
00238   myDesiredPanPos += myPosIncrement;
00239 
00240   if (myDesiredPanPos > myPTU.getMaxPosPan())
00241     myDesiredPanPos = myPTU.getMaxPosPan();
00242 }
00243 
00244 void KeyPTU::right(void)
00245 {
00246   myDesiredPanPos -= myPosIncrement;
00247 
00248   if (myDesiredPanPos < myPTU.getMaxNegPan())
00249     myDesiredPanPos = myPTU.getMaxNegPan();
00250 }
00251 
00252 void KeyPTU::up(void)
00253 {
00254   myDesiredTiltPos += myPosIncrement;
00255  
00256   if (myDesiredTiltPos > myPTU.getMaxPosTilt())
00257     myDesiredTiltPos = myPTU.getMaxPosTilt();
00258 }
00259 
00260 void KeyPTU::down(void)
00261 {
00262   myDesiredTiltPos -= myPosIncrement;
00263 
00264   if (myDesiredTiltPos < myPTU.getMaxNegTilt())
00265     myDesiredTiltPos = myPTU.getMaxNegTilt();
00266 }
00267 
00268 void KeyPTU::space(void)
00269 {
00270   myReset = true;
00271 }
00272 
00273 void KeyPTU::i(void)
00274 {
00275   myInit = true;
00276 }
00277 
00278 void KeyPTU::plus(void)
00279 {
00280   mySlew += mySlewIncrement;
00281 
00282   if (mySlew > myPTU.getMaxPanSlew())
00283     mySlew = myPTU.getMaxPanSlew();
00284 
00285   status();
00286 }
00287 
00288 void KeyPTU::minus(void)
00289 {
00290   mySlew -= mySlewIncrement;
00291 
00292   if (mySlew < myPTU.getMinPanSlew())
00293     mySlew = myPTU.getMinPanSlew();
00294 
00295   status();
00296 }
00297 
00298 void KeyPTU::greater(void)
00299 {
00300   myPosIncrement += posIncIncrement;
00301   
00302   if (myPosIncrement > myPTU.getMaxPosPan())
00303     myPosIncrement = myPTU.getMaxPosPan();
00304 
00305   status();
00306 }
00307 
00308 void KeyPTU::less(void)
00309 {
00310   myPosIncrement -= posIncIncrement;
00311 
00312   if (myPosIncrement < 0)
00313     myPosIncrement = 0;
00314 
00315   status();
00316 }
00317 
00318 void KeyPTU::a(void)
00319 {
00320   myPTU.awaitExec();   
00321   ArLog::log(ArLog::Normal, "AwaitExecution command sent");
00322 }
00323 
00324 void KeyPTU::z(void)
00325 {
00326   myPTU.pan(0);
00327   myPTU.awaitExec();
00328   myPTU.tilt(0);
00329   myPTU.awaitExec();
00330   myDesiredPanPos = 0;
00331   myDesiredTiltPos = 0;
00332   status();
00333 }
00334 
00335 void KeyPTU::question(void)
00336 {
00337   ArLog::log(ArLog::Normal, "\r\nCommands:\r\n_________________\r\n");
00338   ArLog::log(ArLog::Normal, "UP,DOWN    -- tilt up/down by one positional increment");
00339   ArLog::log(ArLog::Normal, "LEFT,RIGHT -- pan left/right by one positional increment");
00340   ArLog::log(ArLog::Normal, "SPACE      -- perform reset calibration");
00341   ArLog::log(ArLog::Normal, "I          -- initialize PTU to default settings");
00342   ArLog::log(ArLog::Normal, "<,>        -- increase/decrease the posIncrement by 1 degree");
00343   ArLog::log(ArLog::Normal, "+,-        -- increase/decrease the speed by 1 degree/sec");
00344   ArLog::log(ArLog::Normal, "A          -- awaits the completion of last issued positional command");
00345   ArLog::log(ArLog::Normal, "R          -- change pan/tilt movements to relative or absolute movements");
00346   ArLog::log(ArLog::Normal, "Z          -- move pan and tilt axes to zero");
00347   ArLog::log(ArLog::Normal, "M          -- Enter or Exit monitor mode");
00348   ArLog::log(ArLog::Normal, "H          -- Halt all motion");
00349   ArLog::log(ArLog::Normal, "S          -- print current variable values");
00350   ArLog::log(ArLog::Normal, "ESC        -- exit program");
00351   ArLog::log(ArLog::Normal, "\r\n");
00352 }
00353 
00354 void KeyPTU::status(void)
00355 {
00356   ArLog::log(ArLog::Normal, "\r\nStatus:\r\n_________________\r\n");
00357   ArLog::log(ArLog::Normal, "Pan Position       = %.1f deg", myPTU.getPan());
00358   ArLog::log(ArLog::Normal, "Tilt Position      = %.1f deg", myPTU.getTilt());
00359   ArLog::log(ArLog::Normal, "Pan Slew Rate      = %d deg/sec", myPTU.getPanSlew());
00360   ArLog::log(ArLog::Normal, "Tilt Slew Rate     = %d deg/sec", myPTU.getTiltSlew());
00361   ArLog::log(ArLog::Normal, "Position Increment = %d deg", myPosIncrement);
00362   if (myAbsolute)
00363     ArLog::log(ArLog::Normal, "Positional-movements using absolute commands");
00364   else
00365     ArLog::log(ArLog::Normal, "Positional-movements using relative commands");
00366   ArLog::log(ArLog::Normal, "\r\n");
00367 }
00368 
00369 void KeyPTU::m(void)
00370 {
00371   if (!myMonitor)
00372   {
00373     ArLog::log(ArLog::Normal, "Entering Monitor mode - hit 'M' to disable");
00374     myMonitor = true;
00375     myPTU.initMon(-60,60,30,-30);
00376   }
00377   else
00378   {
00379     myPTU.blank();  //Blank packet exits monitor mode
00380     myMonitor = false;
00381   }
00382 }
00383 
00384 void KeyPTU::h(void)
00385 {
00386   myPTU.haltAll();
00387 }
00388 
00389 void KeyPTU::r(void)
00390 {
00391   if (!myAbsolute)
00392   {
00393     myAbsolute = true;
00394   }
00395   else
00396   {
00397     myAbsolute = false;
00398   }
00399   status();
00400 }
00401 
00402 
00403 // the important function
00404 void KeyPTU::drive(void)
00405 {
00406 
00407   // if the PTU isn't initialized, initialize it here... it has to be 
00408   // done here instead of above because it needs to be done when the 
00409   // robot is connected
00410   if (!myPTUInited && myRobot->isConnected())
00411   {
00412     myPTU.init();
00413     myPTU.resetCalib();
00414     myPTU.awaitExec();
00415     myPTU.regStatPower();
00416     myPTU.regMotPower();
00417     mySlew = myPTU.getPanSlew(); //uses only pan slew rate
00418     myPTU.awaitExec();
00419     myPTUInited = true;
00420     myInit = false;
00421     myAbsolute = true;
00422   }
00423 
00424   if (myInit == true)
00425   {
00426     myPTU.init();
00427     myInit = false;
00428     myDesiredPanPos = myPTU.getPan();
00429     myDesiredTiltPos = myPTU.getTilt();
00430     mySlew = myPTU.getPanSlew(); //uses only pan slew rate
00431     myReset = false;
00432   }
00433 
00434   if (myReset == true)
00435   {
00436     myPTU.resetCalib();
00437     myPTU.awaitExec();
00438     myDesiredPanPos = myPTU.getPan();
00439     myDesiredTiltPos = myPTU.getTilt();
00440     myReset = false;
00441   }
00442   else
00443   {
00444 
00445     if (myDesiredPanPos != myPTU.getPan())
00446     {
00447       if (myAbsolute)
00448         myPTU.pan(myDesiredPanPos);
00449       else
00450         myPTU.panRel(myDesiredPanPos - myPTU.getPan());
00451     }
00452 
00453     if (myDesiredTiltPos != myPTU.getTilt())
00454     {
00455       if (myAbsolute)
00456         myPTU.tilt(myDesiredTiltPos);
00457       else
00458         myPTU.tiltRel(myDesiredTiltPos - myPTU.getTilt());
00459     }
00460 
00461     if (mySlew != myPTU.getPanSlew())
00462     {
00463       myPTU.panSlew(mySlew);
00464       myPTU.tiltSlew(mySlew);
00465     }
00466 
00467   }
00468 
00469 }
00470 
00471 int main(int argc, char **argv) 
00472 { 
00473   Aria::init();
00474 
00475   // command-line arguments and robots connection
00476   ArArgumentParser argParser(&argc, argv);
00477   argParser.loadDefaultArguments();
00478   ArSimpleConnector con(&argParser);
00479 
00480   // the robot, but turn state reflection off (so we have no mobility control in
00481   // this program)
00482   ArRobot robot(NULL, false);
00483 
00484   // an object for keyboard control, class defined above, this also adds itself as a user task
00485   KeyPTU ptu(&robot);
00486 
00487   // parse command-line arguments (i.e. connection options for simple connector)
00488   if(!Aria::parseArgs())
00489   {
00490     Aria::logOptions();
00491     return 1;
00492   }
00493 
00494   // connect to the robot
00495   if (!con.connectRobot(&robot))
00496   {
00497     ArLog::log(ArLog::Terse, "Error connecting to robot!");
00498     Aria::shutdown();
00499     return 1;
00500   }
00501 
00502 
00503   // turn off the sonar
00504   robot.comInt(ArCommands::SONAR, 0);
00505 
00506   printf("Press '?' for available commands\r\n");
00507 
00508   // run, if we lose connection to the robot, exit
00509   robot.run(true);
00510   
00511   Aria::shutdown();
00512   return 0;
00513 }
00514 

Generated on Fri Jul 31 12:36:37 2009 for Aria by  doxygen 1.4.7