Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages | Examples

Aria.cpp

00001 /*
00002 MobileRobots Advanced Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004, 2005 ActivMedia Robotics LLC
00004 Copyright (C) 2006, 2007 MobileRobots Inc.
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 MobileRobots for information about a commercial version of ARIA at 
00022 robots@mobilerobots.com or 
00023 MobileRobots Inc, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 */
00025 
00026 #include "ArExport.h"
00027 #include "Aria.h"
00028 #include "ArSocket.h"
00029 #include "ArSignalHandler.h"
00030 #include "ArKeyHandler.h"
00031 #include "ArJoyHandler.h"
00032 #ifndef ARINTERFACE
00033 #include "ArModuleLoader.h"
00034 #include "ArRobotJoyHandler.h"
00035 #endif // ARINTERFACE
00036 
00037 ArGlobalFunctor1<int> Aria::ourSignalHandlerCB(&Aria::signalHandlerCB);
00038 ArMutex Aria::ourShuttingDownMutex;
00039 bool Aria::ourShuttingDown=false;
00040 bool Aria::ourExiting=false;
00041 std::string Aria::ourDirectory="";
00042 std::list<ArFunctor*> Aria::ourInitCBs;
00043 std::list<ArFunctor*> Aria::ourUninitCBs;
00044 ArKeyHandler *Aria::ourKeyHandler = NULL;
00045 ArJoyHandler *Aria::ourJoyHandler = NULL;
00046 bool Aria::ourInited = false;
00047 bool Aria::ourRunning = false;
00048 ArMutex Aria::ourExitCallbacksMutex;
00049 std::multimap<int, ArFunctor *> Aria::ourExitCallbacks;
00050 bool Aria::ourSigHandleExitNotShutdown = true;
00051 std::multimap<int, ArRetFunctor<bool> *> Aria::ourParseArgCBs;
00052 ArLog::LogLevel Aria::ourParseArgsLogLevel = ArLog::Verbose;
00053 std::multimap<int, ArFunctor *> Aria::ourLogOptionsCBs;
00054 
00055 #ifndef ARINTERFACE
00056 std::list<ArRobot*> Aria::ourRobots;
00057 ArConfig Aria::ourConfig;
00058 ArRobotJoyHandler *Aria::ourRobotJoyHandler = NULL;
00059 ArStringInfoGroup Aria::ourInfoGroup;
00060 #endif // ARINTERFACE
00061 
00091 AREXPORT void Aria::init(SigHandleMethod method, bool initSockets, 
00092              bool sigHandleExitNotShutdown)
00093 {
00094   std::list<ArFunctor*>::iterator iter;
00095   std::string str;
00096   char buf[1024];
00097 
00098   if (ourInited == true)
00099     return;
00100 
00101   ourRunning = true;
00102 #ifndef WIN32
00103   srand48(time(NULL));
00104 #endif
00105 
00106   ArThread::init();
00107 
00108   char* overrideSigMethod = getenv("ARIA_SIGHANDLE_METHOD");
00109   if(overrideSigMethod)
00110   {
00111     ArLog::log(ArLog::Terse, "Overriding signal handler method with %s from ARIA_SIGHANDLE_METHOD environment variable.", overrideSigMethod);
00112     if(!strcmp(overrideSigMethod, "NONE"))
00113       method = SIGHANDLE_NONE;
00114     else if(!strcmp(overrideSigMethod, "SINGLE"))
00115       method = SIGHANDLE_SINGLE;
00116     else if(!strcmp(overrideSigMethod, "THREAD"))
00117       method = SIGHANDLE_THREAD;
00118   }
00119 
00120   if (method != SIGHANDLE_NONE)
00121   {
00122     ArSignalHandler::addHandlerCB(&ourSignalHandlerCB, ArListPos::LAST);
00123     ArSignalHandler::blockCommon();
00124     ArSignalHandler::handle(ArSignalHandler::SigHUP);
00125     ArSignalHandler::handle(ArSignalHandler::SigINT);
00126     ArSignalHandler::handle(ArSignalHandler::SigQUIT);
00127     ArSignalHandler::handle(ArSignalHandler::SigTERM);
00128     ArSignalHandler::handle(ArSignalHandler::SigPIPE);
00129     if (method == SIGHANDLE_SINGLE)
00130         ArSignalHandler::createHandlerNonThreaded();
00131     else if (method == SIGHANDLE_THREAD)
00132     {
00133       ArSignalHandler::blockCommonThisThread();
00134       ArSignalHandler::createHandlerThreaded();
00135     }
00136   }
00137 
00138   if (initSockets)
00139     ArSocket::init();
00140 
00141   if (ourDirectory.length() == 0)
00142   {
00143     if (getenv("ARIA") != NULL)
00144     {
00145       setDirectory(getenv("ARIA"));
00146     }
00147     else
00148     {
00149 #ifndef WIN32
00150       ArUtil::getStringFromFile("/etc/Aria", buf, sizeof(buf));
00151       str = buf;
00152 #else // WIN32
00153       if (ArUtil::findFirstStringInRegistry(
00154           "SOFTWARE\\MobileRobots\\Aria",
00155           "Install Directory", buf, 1024))
00156         str = buf;
00157       else
00158         if (ArUtil::findFirstStringInRegistry(
00159             "SOFTWARE\\ActivMedia Robotics\\Aria",
00160             "Install Directory", buf, 1024))
00161           str = buf;
00162         else
00163           str = "";
00164         
00165   #endif // WIN32
00166         if (str.length() > 0)
00167         {
00168     setDirectory(str.c_str());
00169         }
00170         else
00171         {
00172   #ifndef ARINTERFACE
00173     ArLog::log(ArLog::Terse, "NonCritical Error: ARIA could not find where it is located.");
00174   #else
00175     ArLog::log(ArLog::Verbose, "NonCritical Error: ARIA could not find where it is located.");
00176   #endif
00177         }
00178       }
00179     }
00180     ourSigHandleExitNotShutdown = sigHandleExitNotShutdown;
00181 
00182   ourInited = true;
00183   for (iter=ourInitCBs.begin(); iter !=  ourInitCBs.end(); ++iter)
00184     (*iter)->invoke();
00185   ArArgumentParser::addDefaultArgumentFile("/etc/Aria.args");
00186   ArArgumentParser::addDefaultArgumentEnv("ARIAARGS");
00187   
00188 }
00189 
00195 AREXPORT void Aria::uninit()
00196 {
00197   std::list<ArFunctor*>::iterator iter;
00198 
00199   for (iter=ourUninitCBs.begin(); iter != ourUninitCBs.end(); ++iter)
00200     (*iter)->invoke();
00201 
00202 #ifndef ARINTERFACE
00203   ArModuleLoader::closeAll();
00204 #endif // ARINTERFACE
00205   ArSocket::shutdown();
00206 }
00207 
00212 AREXPORT void Aria::addInitCallBack(ArFunctor *cb, ArListPos::Pos position)
00213 {
00214   if (position == ArListPos::FIRST)
00215     ourInitCBs.push_front(cb);
00216   else
00217     ourInitCBs.push_back(cb);
00218 }
00219 
00227 AREXPORT void Aria::addUninitCallBack(ArFunctor *cb, ArListPos::Pos position)
00228 {
00229   if (position == ArListPos::FIRST)
00230     ourUninitCBs.push_front(cb);
00231   else
00232     ourUninitCBs.push_back(cb);
00233 }
00234 
00241 AREXPORT void Aria::shutdown()
00242 {
00243   bool doExit=false;
00244 
00245   ourShuttingDownMutex.lock();
00246   ourRunning = false;
00247   if (ourShuttingDown)
00248     doExit=true;
00249   else
00250     ourShuttingDown=true;
00251   ourShuttingDownMutex.unlock();
00252 
00253   if (doExit)
00254     return;
00255 
00256   ArThread::stopAll();
00257   ArThread::joinAll();
00258   uninit();
00259 }
00260 
00267 AREXPORT void Aria::exit(int exitCode)
00268 {
00269   bool doReturn = false;
00270   ourShuttingDownMutex.lock();
00271   ourRunning = false;
00272   if (ourExiting)
00273     doReturn=true;
00274   else
00275     ourExiting=true;
00276   ourShuttingDownMutex.unlock();
00277 
00278   if (doReturn)
00279     return;
00280 
00281   callExitCallbacks();
00282   ::exit(exitCode);
00283 }
00284 
00285 AREXPORT void Aria::callExitCallbacks(void)
00286 {
00287   ourRunning = false;
00288   std::multimap<int, ArFunctor *>::reverse_iterator it;
00289  
00290   ourExitCallbacksMutex.lock();
00291   ArLog::log(ArLog::Verbose, "Aria::exit: Starting exit callbacks");
00292   for (it = ourExitCallbacks.rbegin(); it != ourExitCallbacks.rend(); it++)
00293   {
00294     ArLog::log(ArLog::Verbose, 
00295            "Aria::exit: Calling callback at position %d with name '%s'",
00296            (*it).first, (*it).second->getName());
00297     (*it).second->invoke();
00298   }
00299   ArLog::log(ArLog::Verbose, "Aria::exit: Finished exit callbacks");
00300   ourExitCallbacksMutex.unlock();
00301 } 
00302  
00303 AREXPORT void Aria::addExitCallback(ArFunctor *functor, int position)
00304 {
00305   ourExitCallbacksMutex.lock();
00306   ArLog::log(ArLog::Verbose, 
00307     "Aria::addExitCallback: Adding callback at position %d with name '%s'",
00308          position, functor->getName());
00309   ourExitCallbacks.insert(std::pair<int, ArFunctor *>(position, functor));
00310   ourExitCallbacksMutex.unlock();
00311 }
00312 
00313 /*
00314 AREXPORT void Aria::remExitCallback(ArFunctor *functor)
00315 {
00316   std::multimap<int, ArFunctor *>::iterator it;
00317   
00318   ourExitCallbacksMutex.lock();
00319   for (it = ourExitCallbacks.begin(); it != ourExitCallbacks.end(); it++)
00320   {
00321     if ((*it).second == functor)
00322     {
00323       ourExitCallbacks.erase(it);
00324       ourExitCallbacksMutex.unlock();
00325       return remExitCallback(functor);
00326     }
00327   }
00328   ourExitCallbacksMutex.unlock();
00329 }
00330 */
00331 
00345 AREXPORT void Aria::exitOld(int exitCode)
00346 {
00347   ourRunning = false;
00348   ArThread::cancelAll();
00349   uninit();
00350   ::exit(exitCode);
00351 }
00352 
00353 #ifndef ARINTERFACE
00354 AREXPORT void Aria::addRobot(ArRobot *robot)
00355 {
00356   ourRobots.push_back(robot);
00357 }
00358 
00359 AREXPORT void Aria::delRobot(ArRobot *robot)
00360 {
00361   ourRobots.remove(robot);
00362 }
00363 
00369 AREXPORT ArRobot *Aria::findRobot(char *name)
00370 {
00371   std::string rname;
00372   std::list<ArRobot *>::iterator it;
00373   if (name == NULL)
00374     return NULL;
00375 
00376   rname = name;
00377   for (it = ourRobots.begin(); it != ourRobots.end(); it++)
00378   {
00379     if ((*it)->getName() == rname)
00380       return (*it);
00381   }
00382   return NULL;
00383 
00384 }
00385 
00386 AREXPORT std::list<ArRobot*> * Aria::getRobotList()
00387 {
00388   return(&ourRobots);
00389 }
00390 
00391 #endif // ARINTERFACE
00392 
00393 AREXPORT void Aria::signalHandlerCB(int sig)
00394 {
00395 
00396   // if we want to exit instead of shutdown then do that ( call never returns)
00397   if (ourSigHandleExitNotShutdown)
00398   {
00399     ArLog::log(ArLog::Normal, "Aria: Received signal '%s'. Exiting.",
00400            ArSignalHandler::nameSignal(sig));
00401     Aria::exit(0);
00402     // we shouldn't need this here, since the program should already
00403     // exited... but just in case
00404     ::exit(0);
00405   }
00406 
00407 
00408   ourShuttingDownMutex.lock();
00409   if (!ourRunning)
00410   {
00411     ourShuttingDownMutex.unlock();
00412     return;
00413   }
00414   ourShuttingDownMutex.unlock();
00415 
00416 
00417   ArLog::log(ArLog::Normal, "Aria: Received signal '%s'. Shutting down.",
00418          ArSignalHandler::nameSignal(sig));
00419 
00420 #ifndef ARINTERFACE
00421   std::list<ArRobot*>::iterator iter;
00422   if ((sig == ArSignalHandler::SigINT) || (sig == ArSignalHandler::SigHUP) ||
00423       (sig == ArSignalHandler::SigTERM))
00424   {
00425     for (iter=ourRobots.begin(); iter != ourRobots.end(); ++iter)
00426       (*iter)->stopRunning();
00427   }
00428 #endif //ARINTERFACE
00429 
00430   // I'm disregarding this advice below since I can't seem to get
00431   // anything else to work well and haven't seen problems from it
00432 
00433   // dont do an Aria::shutdown() here because we want the main()
00434   // function to do the ArThread::joinAll(). Otherwise variables on
00435   // the stack frame of main() may get destructed if main() happens to
00436   // exit before other threads.  And some of those variables may be
00437   // used by those threads.
00438   shutdown();
00439 }
00440 
00449 AREXPORT void Aria::setDirectory(const char *directory)
00450 {
00451   int ind;
00452   if (directory != NULL)
00453   {
00454     ourDirectory = directory;
00455     ind = strlen(directory) - 1;
00456     if (ind < 0)
00457       ind = 0;
00458     if (directory[ind] != '/' && directory[ind] != '\\')
00459     {
00460 #ifdef WIN32
00461       ourDirectory += "\\";
00462 #else // win32
00463       ourDirectory += "/";
00464 #endif // win32
00465     }
00466 #ifndef ARINTERFACE
00467     ourConfig.setBaseDirectory(ourDirectory.c_str());
00468 #endif // ARINTERFACE
00469   }
00470 }
00471 
00478 AREXPORT const char *Aria::getDirectory(void)
00479 {
00480   return ourDirectory.c_str();
00481 }
00482 
00484 AREXPORT void Aria::setKeyHandler(ArKeyHandler *keyHandler)
00485 {
00486   ourKeyHandler = keyHandler;
00487 }
00488 
00490 AREXPORT ArKeyHandler *Aria::getKeyHandler(void)
00491 {
00492   return ourKeyHandler;
00493 }
00494 
00496 AREXPORT void Aria::setJoyHandler(ArJoyHandler *joyHandler)
00497 {
00498   ourJoyHandler = joyHandler;
00499 }
00500 
00502 AREXPORT ArJoyHandler *Aria::getJoyHandler(void)
00503 {
00504   return ourJoyHandler;
00505 }
00506 
00507 #ifndef ARINTERFACE
00508 
00509 AREXPORT void Aria::setRobotJoyHandler(ArRobotJoyHandler *robotJoyHandler)
00510 {
00511   ourRobotJoyHandler = robotJoyHandler;
00512 }
00513 
00515 AREXPORT ArRobotJoyHandler *Aria::getRobotJoyHandler(void)
00516 {
00517   return ourRobotJoyHandler;
00518 }
00519 
00523 AREXPORT ArConfig *Aria::getConfig(void)
00524 {
00525   return &ourConfig;
00526 }
00527 
00531 AREXPORT ArStringInfoGroup *Aria::getInfoGroup(void)
00532 {
00533   return &ourInfoGroup;
00534 }
00535 
00536 #endif // ARINTERFACE
00537 
00543 AREXPORT bool Aria::getRunning(void)
00544 {
00545   return ourRunning;
00546 }
00547 
00548 AREXPORT bool Aria::parseArgs(void)
00549 {
00550   std::multimap<int, ArRetFunctor<bool> *>::reverse_iterator it;
00551   ArRetFunctor<bool> *callback;
00552 
00553   ArLog::log(ourParseArgsLogLevel, "Aria: Parsing arguments");
00554   for (it = ourParseArgCBs.rbegin(); it != ourParseArgCBs.rend(); it++)
00555   {
00556     callback = (*it).second;
00557     if (callback->getName() != NULL && callback->getName()[0] != '\0')
00558       ArLog::log(ourParseArgsLogLevel, 
00559          "Aria: Calling parse arg functor '%s' (%d)", 
00560          callback->getName(), (*it).first);
00561     else
00562       ArLog::log(ourParseArgsLogLevel, 
00563          "Aria: Calling unnamed parse arg functor (%d)", 
00564          (*it).first);
00565 
00566     if (!callback->invokeR())
00567     {
00568       return false;
00569     }
00570   }
00571   return true;
00572 }
00573 
00574 AREXPORT void Aria::logOptions(void)
00575 {
00576   std::multimap<int, ArFunctor *>::reverse_iterator it;
00577 
00578   for (it = ourLogOptionsCBs.rbegin(); it != ourLogOptionsCBs.rend(); it++)
00579   {
00580     (*it).second->invoke();
00581     ArLog::log(ArLog::Terse, "");
00582     ArLog::log(ArLog::Terse, "");
00583   }
00584 }
00585 
00586 AREXPORT void Aria::addParseArgsCB(ArRetFunctor<bool> *functor, 
00587                       int position)
00588 {
00589   ourParseArgCBs.insert(std::pair<int, ArRetFunctor<bool> *>(position, 
00590                                  functor));
00591 }
00592 
00593 AREXPORT void Aria::setParseArgLogLevel(ArLog::LogLevel level)
00594 {
00595   ourParseArgsLogLevel = level;
00596 }
00597 
00598 AREXPORT void Aria::addLogOptionsCB(ArFunctor *functor, int position)
00599 {
00600   ourLogOptionsCBs.insert(std::pair<int, ArFunctor *>(position, functor));
00601 }
00602 
00603 

Generated on Tue Feb 20 10:51:40 2007 for Aria by  doxygen 1.4.0