This program uses key commands to control the pan, tilt, and zoom of the camera. It uses the same slew for the pan and tilt axes. It defaults to use the microcontroller port Aux1. See the setport comments below to use the computer's serial port, or a different aux port on the microcontroller.
Commands: _________________
UP,DOWN -- tilt up/down by 1 degree LEFT,RIGHT -- pan left/right by 1 degree X,C -- zoom in/out by 10 units (80 total) I -- initialize PTU to default settings >,< -- increase/decrease the positional increment by one 1 degree +,- -- increase/decrease the slew by 5 degrees/sec Z -- move pan and tilt axes to zero H -- Halt all motion S -- Status of camera position and variable values P -- Power on/off the camera ESC -- Exit program
00001 #include "Aria.h" 00002 00026 /* 00027 This class is the core of this demo, it adds itself to the robot given 00028 as a user task, then drives the PTZ camera from the keyboard 00029 */ 00030 class KeyPTU 00031 { 00032 public: 00033 // constructor 00034 KeyPTU(ArRobot *robot); 00035 // destructor, its just empty 00036 ~KeyPTU(void) {} 00037 00038 void up(void); 00039 void down(void); 00040 void left(void); 00041 void right(void); 00042 00043 void plus(void); 00044 void minus(void); 00045 void greater(void); 00046 void less(void); 00047 void question(void); 00048 void status(void); 00049 00050 void c(void); 00051 void h(void); 00052 void i(void); 00053 void p(void); 00054 void x(void); 00055 void z(void); 00056 00057 void r(void); 00058 // the callback function 00059 void drive(void); 00060 00061 protected: 00062 00063 ArTime myExerciseTime; 00064 00065 int myPanSlew; 00066 int myTiltSlew; 00067 int myPosIncrement; 00068 int mySlewIncrement; 00069 int myZoomIncrement; 00070 00071 bool myMonitor; 00072 bool myInit; 00073 bool myAbsolute; 00074 bool myExercise; 00075 00076 void exercise(void) { myExercise = !myExercise; } 00077 void autoupdate(void); 00078 00079 ArFunctorC<KeyPTU> myUpCB; 00080 ArFunctorC<KeyPTU> myDownCB; 00081 ArFunctorC<KeyPTU> myLeftCB; 00082 ArFunctorC<KeyPTU> myRightCB; 00083 00084 ArFunctorC<KeyPTU> myPlusCB; 00085 ArFunctorC<KeyPTU> myMinusCB; 00086 ArFunctorC<KeyPTU> myGreaterCB; 00087 ArFunctorC<KeyPTU> myLessCB; 00088 ArFunctorC<KeyPTU> myQuestionCB; 00089 ArFunctorC<KeyPTU> mySCB; 00090 00091 ArFunctorC<KeyPTU> myECB; 00092 ArFunctorC<KeyPTU> myACB; 00093 00094 ArFunctorC<KeyPTU> myCCB; 00095 ArFunctorC<KeyPTU> myHCB; 00096 ArFunctorC<KeyPTU> myICB; 00097 ArFunctorC<KeyPTU> myPCB; 00098 ArFunctorC<KeyPTU> myXCB; 00099 ArFunctorC<KeyPTU> myZCB; 00100 00101 ArFunctorC<KeyPTU> myRCB; 00102 00103 // the PTU 00104 ArVCC4 myPTU; 00105 00106 // the serial connection, in case we are connected to a computer 00107 // serial port 00108 ArSerialConnection myCon; 00109 00110 // whether or not we've requested that the Camera initialize itself 00111 bool myPTUInitRequested; 00112 // pointer to the robot 00113 ArRobot *myRobot; 00114 // callback for the drive function 00115 ArFunctorC<KeyPTU> myDriveCB; 00116 }; 00117 00118 /* 00119 Constructor, sets the robot pointer, and some initial values, also note the 00120 use of constructor chaining on myPTU and myDriveCB. 00121 */ 00122 KeyPTU::KeyPTU(ArRobot *robot) : 00123 myUpCB(this, &KeyPTU::up), 00124 myDownCB(this, &KeyPTU::down), 00125 myLeftCB(this, &KeyPTU::left), 00126 myRightCB(this, &KeyPTU::right), 00127 myPlusCB(this, &KeyPTU::plus), 00128 myMinusCB(this, &KeyPTU::minus), 00129 myGreaterCB(this, &KeyPTU::greater), 00130 myLessCB(this, &KeyPTU::less), 00131 myQuestionCB(this, &KeyPTU::question), 00132 mySCB(this, &KeyPTU::status), 00133 myECB(this, &KeyPTU::exercise), 00134 myACB(this, &KeyPTU::autoupdate), 00135 myCCB(this, &KeyPTU::c), 00136 myHCB(this, &KeyPTU::h), 00137 myICB(this, &KeyPTU::i), 00138 myPCB(this, &KeyPTU::p), 00139 myXCB(this, &KeyPTU::x), 00140 myZCB(this, &KeyPTU::z), 00141 myRCB(this, &KeyPTU::r), 00142 00143 myPTU(robot), 00144 myDriveCB(this, &KeyPTU::drive) 00145 { 00146 // set the robot pointer and add the KeyPTU as user task 00147 ArKeyHandler *keyHandler; 00148 myRobot = robot; 00149 myRobot->addSensorInterpTask("KeyPTU", 50, &myDriveCB); 00150 00151 myPTU.setLEDControlMode(2); 00152 myExerciseTime.setToNow(); 00153 myExercise = false; 00154 00155 // SETPORT Uncomment the following to run the camera off 00156 // of the computer's serial port, rather than the microcontroller 00157 00158 // uncomment below here 00159 /* 00160 #ifdef WIN32 00161 myCon.setPort("COM2"); 00162 #else 00163 myCon.setPort("/dev/ttyS0"); 00164 #endif 00165 myPTU.setDeviceConnection(&myCon); 00166 */ 00167 // to here 00168 00169 // or use this next line to set the aux port 00170 //myPTU.setAuxPort(2); 00171 00172 00173 if ((keyHandler = Aria::getKeyHandler()) == NULL) 00174 { 00175 keyHandler = new ArKeyHandler; 00176 Aria::setKeyHandler(keyHandler); 00177 myRobot->attachKeyHandler(keyHandler); 00178 } 00179 00180 if (!keyHandler->addKeyHandler(ArKeyHandler::UP, &myUpCB)) 00181 ArLog::log(ArLog::Terse, "The key handler already has a key for up, keydrive will not work correctly."); 00182 if (!keyHandler->addKeyHandler(ArKeyHandler::DOWN, &myDownCB)) 00183 ArLog::log(ArLog::Terse, "The key handler already has a key for down, keydrive will not work correctly."); 00184 if (!keyHandler->addKeyHandler(ArKeyHandler::LEFT, &myLeftCB)) 00185 ArLog::log(ArLog::Terse, 00186 "The key handler already has a key for left, keydrive will not work correctly."); 00187 if (!keyHandler->addKeyHandler(ArKeyHandler::RIGHT, &myRightCB)) 00188 ArLog::log(ArLog::Terse, 00189 "The key handler already has a key for right, keydrive will not work correctly."); 00190 00191 if (!keyHandler->addKeyHandler('+', &myPlusCB)) 00192 ArLog::log(ArLog::Terse, 00193 "The key handler already has a key for '+', keydrive will not work correctly."); 00194 if (!keyHandler->addKeyHandler('-', &myMinusCB)) 00195 ArLog::log(ArLog::Terse, 00196 "The key handler already has a key for '-', keydrive will not work correctly."); 00197 if (!keyHandler->addKeyHandler('>', &myGreaterCB)) 00198 ArLog::log(ArLog::Terse, 00199 "The key handler already has a key for '>', keydrive will not work correctly."); 00200 if (!keyHandler->addKeyHandler('<', &myLessCB)) 00201 ArLog::log(ArLog::Terse, 00202 "The key handler already has a key for '<', keydrive will not work correctly."); 00203 if (!keyHandler->addKeyHandler('?', &myQuestionCB)) 00204 ArLog::log(ArLog::Terse, 00205 "The key handler already has a key for '?', keydrive will not work correctly."); 00206 00207 if (!keyHandler->addKeyHandler('c', &myCCB)) 00208 ArLog::log(ArLog::Terse, 00209 "The key handler already has a key for 'C', keydrive will not work correctly."); 00210 if (!keyHandler->addKeyHandler('h', &myHCB)) 00211 ArLog::log(ArLog::Terse, 00212 "The key handler already has a key for 'H', keydrive will not work correctly."); 00213 if (!keyHandler->addKeyHandler('i', &myICB)) 00214 ArLog::log(ArLog::Terse, 00215 "The key handler already has a key for 'I', keydrive will not work correctly."); 00216 if (!keyHandler->addKeyHandler('p', &myPCB)) 00217 ArLog::log(ArLog::Terse, 00218 "The key handler already has a key for 'P', keydrive will not work correctly."); 00219 if (!keyHandler->addKeyHandler('r', &myRCB)) 00220 ArLog::log(ArLog::Terse, 00221 "The key handler already has a key for 'R', keydrive will not work correctly."); 00222 00223 if (!keyHandler->addKeyHandler('s', &mySCB)) 00224 ArLog::log(ArLog::Terse, 00225 "The key handler already has a key for 'S', keydrive will not work correctly."); 00226 if (!keyHandler->addKeyHandler('x', &myXCB)) 00227 ArLog::log(ArLog::Terse, 00228 "The key handler already has a key for 'X', keydrive will not work correctly."); 00229 if (!keyHandler->addKeyHandler('z', &myZCB)) 00230 ArLog::log(ArLog::Terse, 00231 "The key handler already has a key for 'Z', keydrive will not work correctly."); 00232 if (!keyHandler->addKeyHandler('a', &myACB)) 00233 ArLog::log(ArLog::Terse, "The key handler already has a key for 'A', keydrive will not work correctly."); 00234 if (!keyHandler->addKeyHandler('e', &myECB)) 00235 ArLog::log(ArLog::Terse, "The key handler already has a key for 'E', keydrive will not work correctly."); 00236 00237 00238 00239 // initialize some variables 00240 00241 myPTUInitRequested = false; 00242 myPosIncrement = 1; 00243 mySlewIncrement = 5; 00244 myZoomIncrement = 50; 00245 00246 } 00247 00248 void KeyPTU::autoupdate(void) 00249 { 00250 if (myPTU.getAutoUpdate()) 00251 myPTU.disableAutoUpdate(); 00252 else 00253 myPTU.enableAutoUpdate(); 00254 } 00255 00256 void KeyPTU::right(void) 00257 { 00258 myPTU.panRel(myPosIncrement); 00259 } 00260 00261 void KeyPTU::left(void) 00262 { 00263 myPTU.panRel(-myPosIncrement); 00264 } 00265 00266 void KeyPTU::up(void) 00267 { 00268 myPTU.tiltRel(myPosIncrement); 00269 } 00270 00271 void KeyPTU::down(void) 00272 { 00273 myPTU.tiltRel(-myPosIncrement); 00274 } 00275 00276 void KeyPTU::x(void) 00277 { 00278 myPTU.zoom(myPTU.getZoom() + myZoomIncrement); 00279 } 00280 00281 void KeyPTU::c(void) 00282 { 00283 myPTU.zoom(myPTU.getZoom() - myZoomIncrement); 00284 } 00285 00286 void KeyPTU::i(void) 00287 { 00288 myPTU.init(); 00289 } 00290 00291 void KeyPTU::plus(void) 00292 { 00293 myPTU.panSlew(myPTU.getPanSlew() + mySlewIncrement); 00294 myPTU.tiltSlew(myPTU.getTiltSlew() + mySlewIncrement); 00295 00296 status(); 00297 } 00298 00299 void KeyPTU::minus(void) 00300 { 00301 myPTU.panSlew(myPTU.getPanSlew() - mySlewIncrement); 00302 myPTU.tiltSlew(myPTU.getTiltSlew() - mySlewIncrement); 00303 00304 status(); 00305 } 00306 00307 void KeyPTU::greater(void) 00308 { 00309 myPosIncrement += 1; 00310 00311 if (myPosIncrement > myPTU.getMaxPosPan()) //Use pan range as reference for largest allowable positional increment 00312 myPosIncrement = myPTU.getMaxPosPan(); 00313 00314 status(); 00315 } 00316 00317 void KeyPTU::less(void) 00318 { 00319 myPosIncrement -= 1; 00320 00321 if (myPosIncrement < 0) 00322 myPosIncrement = 0; 00323 00324 status(); 00325 } 00326 00327 00328 void KeyPTU::z(void) 00329 { 00330 myPTU.panTilt(0,0); 00331 myPTU.zoom(0); 00332 status(); 00333 } 00334 00335 00336 void KeyPTU::r(void) 00337 { 00338 myPTU.reset(); 00339 } 00340 00341 00342 void KeyPTU::question(void) 00343 { 00344 ArLog::log(ArLog::Normal, "\r\nCommands:\r\n_________________\r\n"); 00345 ArLog::log(ArLog::Normal, "UP,DOWN -- tilt up/down by 1 increment"); 00346 ArLog::log(ArLog::Normal, "LEFT,RIGHT -- pan left/right by 1 increment"); 00347 ArLog::log(ArLog::Normal, "X,C -- zoom in/out by 50 units (2140 max)"); 00348 ArLog::log(ArLog::Normal, "I -- initialize PTU to default settings"); 00349 ArLog::log(ArLog::Normal, ">,< -- increase/decrease the positional increment by 1 degree"); 00350 ArLog::log(ArLog::Normal, "+,- -- increase/decrease the slew by 5 degrees/sec"); 00351 ArLog::log(ArLog::Normal, "Z -- move pan and tilt axes to zero"); 00352 ArLog::log(ArLog::Normal, "E -- toggle exercise mode"); 00353 ArLog::log(ArLog::Normal, "A -- toggle autoupdate mode"); 00354 ArLog::log(ArLog::Normal, "H -- Halt all motion"); 00355 ArLog::log(ArLog::Normal, "S -- Status of camera position and variable values"); 00356 ArLog::log(ArLog::Normal, "P -- Power on/off the camera"); 00357 ArLog::log(ArLog::Normal, "R -- Reset the camera"); 00358 ArLog::log(ArLog::Normal, "ESC -- Exit program"); 00359 ArLog::log(ArLog::Normal, "\r\n"); 00360 } 00361 00362 void KeyPTU::status(void) 00363 { 00364 ArLog::log(ArLog::Normal, "\r\nStatus:\r\n_________________________\r\n"); 00365 ArLog::log(ArLog::Normal, "Pan Position = %.0f deg", myPTU.getPan()); 00366 ArLog::log(ArLog::Normal, "Tilt Position = %.0f deg", myPTU.getTilt()); 00367 ArLog::log(ArLog::Normal, "Zoom Position = %d", myPTU.getZoom()); 00368 ArLog::log(ArLog::Normal, "Pan Slew = %d deg/s", myPTU.getPanSlew()); 00369 ArLog::log(ArLog::Normal, "Tilt Slew = %d deg/s", myPTU.getTiltSlew()); 00370 ArLog::log(ArLog::Normal, "Position Increment = %d deg", myPosIncrement); 00371 ArLog::log(ArLog::Normal, "Autoupdate = %d", myPTU.getAutoUpdate()); 00372 ArLog::log(ArLog::Normal, "Exercise = %d", myExercise); 00373 if (myPTU.getPower()) 00374 ArLog::log(ArLog::Normal, "Power is ON"); 00375 else 00376 ArLog::log(ArLog::Normal, "Power is OFF"); 00377 ArLog::log(ArLog::Normal, "\r\n"); 00378 } 00379 00380 void KeyPTU::h(void) 00381 { 00382 myPTU.haltPanTilt(); 00383 myPTU.haltZoom(); 00384 } 00385 00386 void KeyPTU::p(void) 00387 { 00388 if (myPTU.getPower()) 00389 myPTU.power(0); 00390 else 00391 myPTU.power(1); 00392 00393 status(); 00394 } 00395 00396 // the important function 00397 void KeyPTU::drive(void) 00398 { 00399 // if the PTU isn't initialized, initialize it here... it has to be 00400 // done here instead of above because it needs to be done when the 00401 // robot is connected 00402 if (!myPTUInitRequested && !myPTU.isInitted() && myRobot->isConnected()) 00403 { 00404 printf("\nWaiting for Camera to Initialize\n"); 00405 myAbsolute = true; 00406 myPTUInitRequested = true; 00407 myPTU.init(); 00408 } 00409 00410 // if the camera hasn't initialized yet, then just return 00411 if (myPTUInitRequested && !myPTU.isInitted()) 00412 { 00413 return; 00414 } 00415 00416 if (myPTUInitRequested && myPTU.isInitted()) 00417 { 00418 myPTUInitRequested = false; 00419 myPanSlew = myPTU.getPanSlew(); 00420 myTiltSlew = myPTU.getTiltSlew(); 00421 printf("Done.\n"); 00422 question(); 00423 } 00424 00425 if (myExerciseTime.secSince() > 5 && myExercise) 00426 { 00427 int pan,tilt; 00428 00429 if (ArMath::random()%2) 00430 pan = ArMath::random()%((int)myPTU.getMaxPosPan()); 00431 else 00432 pan = -ArMath::random()%((int)myPTU.getMaxNegPan()); 00433 00434 if (ArMath::random()%2) 00435 tilt = ArMath::random()%((int)myPTU.getMaxPosTilt()); 00436 else 00437 tilt = -ArMath::random()%((int)myPTU.getMaxNegTilt()); 00438 00439 myPTU.panTilt(pan, tilt); 00440 //printf("** %d\n", myRobot->getEstop()); 00441 //printf("--> %x\n", myRobot->getFlags()); 00442 myExerciseTime.setToNow(); 00443 } 00444 00445 } 00446 00447 int main(int argc, char **argv) 00448 { 00449 // just some stuff for returns 00450 std::string str; 00451 // robots connection 00452 ArSerialConnection con; 00453 00454 // the robot, this turns state reflection off 00455 ArRobot robot(NULL, false); 00456 // the joydrive as defined above, this also adds itself as a user task 00457 KeyPTU ptu(&robot); 00458 00459 // mandatory init 00460 Aria::init(); 00461 00462 //ArLog::init(ArLog::StdOut, ArLog::Normal, NULL, true); 00463 00464 con.setPort(ArUtil::COM1); 00465 // set the connection on the robot 00466 robot.setDeviceConnection(&con); 00467 00468 // connect, if we fail, exit 00469 if (!robot.blockingConnect()) 00470 { 00471 printf("Could not connect to robot... exiting\n"); 00472 Aria::shutdown(); 00473 return 1; 00474 } 00475 00476 00477 // turn off the sonar, enable the motors, turn off amigobot sounds 00478 robot.comInt(ArCommands::SONAR, 0); 00479 robot.comInt(ArCommands::ENABLE, 1); 00480 robot.comInt(ArCommands::SOUNDTOG, 0); 00481 00482 printf("Press '?' for available commands\r\n"); 00483 // run, if we lose connection to the robot, exit 00484 robot.run(true); 00485 00486 // shutdown and go away 00487 Aria::shutdown(); 00488 return 0; 00489 } 00490
1.4.7