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
1.4.7