vcc4CameraExample.cpp

This is an example using the Canon VC-C4 Pan/Tilt/Zoom camera.

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 

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