Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

Main.cc

Go to the documentation of this file.
00001 #include "Main.h"
00002 #include "SoundPlay.h"
00003 #include "Motion.h"
00004 #include "Simulator.h"
00005 #include "TimerExecThread.h"
00006 #include "SimConfig.h"
00007 #include "MotionExecThread.h"
00008 
00009 #include "IPC/RegionRegistry.h"
00010 #include "IPC/MessageReceiver.h"
00011 #include "IPC/FailsafeThread.h"
00012 #include "IPC/PollThread.h"
00013 #include "IPC/ThreadedMessageQueue.h"
00014 #include "Motion/Kinematics.h"
00015 #include "Motion/PostureEngine.h"
00016 #include "Wireless/Wireless.h"
00017 #include "Shared/ProjectInterface.h"
00018 #include "Behaviors/BehaviorBase.h"
00019 #include "Events/DataEvent.h"
00020 #include "Events/EventRouter.h"
00021 #include "Shared/Config.h"
00022 #include "Shared/MarkScope.h"
00023 #include "Shared/WorldState.h"
00024 #include "Events/EventBase.h"
00025 
00026 using namespace std;
00027 
00028 Main::Main()
00029   : Process(getID(),getClassName()),
00030   sounds(ipc_setup->registerRegion(SoundPlay::getSoundPlayID(),sizeof(sim::SoundPlayQueue_t))),
00031   motions(ipc_setup->registerRegion(Motion::getMotionCommandID(),sizeof(sim::MotionCommandQueue_t))),
00032   events(ipc_setup->registerRegion(getEventsID(),sizeof(sim::EventQueue_t))),
00033   cameraFrames(ipc_setup->registerRegion(Simulator::getCameraQueueID(),sizeof(sim::CameraQueue_t))),
00034   sensorFrames(ipc_setup->registerRegion(Simulator::getSensorQueueID(),sizeof(sim::SensorQueue_t))),
00035   timerWakeup(ipc_setup->registerRegion(Simulator::getTimerWakeupID(),sizeof(sim::TimerWakeup_t))),
00036   statusRequest(ipc_setup->registerRegion(Simulator::getStatusRequestID(),sizeof(sim::StatusRequest_t))),
00037   motionmanager(ipc_setup->registerRegion(Motion::getMotionManagerID(),sizeof(MotionManager))),
00038   soundmanager(ipc_setup->registerRegion(SoundPlay::getSoundManagerID(),sizeof(SoundManager))),
00039   motionProf(ipc_setup->registerRegion(Motion::getMotionProfilerID(),sizeof(motionProfiler_t))),
00040   soundProf(ipc_setup->registerRegion(SoundPlay::getSoundProfilerID(),sizeof(soundProfiler_t))),
00041   visrecv(NULL), sensrecv(NULL), evtrecv(NULL), timerrecv(NULL), statusrecv(NULL), timerExec(NULL),
00042   visionRead(true), wireless_thread(), worldStateCache(), behaviorLock(),
00043   curimgregion(NULL), img(), lastVisionSN(-1U)
00044 {
00045   new (&(*events)) sim::EventQueue_t;
00046   motman=&(*motionmanager);
00047   sndman=&(*soundmanager);
00048   ::mainProfiler=new mainProfiler_t;
00049   ::motionProfiler=&(*motionProf);
00050   ::soundProfiler=&(*soundProf);
00051 
00052   if(sim::config.multiprocess) {
00053     //Setup wireless
00054     ASSERT(wireless==NULL,"global wireless already initialized before Main?");
00055     wireless = new Wireless();
00056     sout=wireless->socket(Socket::SOCK_STREAM,Wireless::WIRELESS_DEF_RECV_SIZE,Wireless::WIRELESS_DEF_SEND_SIZE*12);
00057     serr=wireless->socket(Socket::SOCK_STREAM,Wireless::WIRELESS_DEF_RECV_SIZE,Wireless::WIRELESS_DEF_SEND_SIZE*4);
00058     wireless->setDaemon(sout);
00059     wireless->setDaemon(serr);
00060     serr->setFlushType(Socket::FLUSH_BLOCKING);
00061     sout->setTextForward();
00062     serr->setForward(sout);
00063     
00064     //Setup Kinematics
00065     ASSERT(kine==NULL,"global kine already initialized before Main?");
00066     kine=new Kinematics();
00067   }
00068   wireless->setCallbackLock(behaviorLock);
00069 
00070   //EventRouter and Config are set up for all processes by main() before fork
00071 }
00072 
00073 Main::~Main() {
00074   if(sim::config.multiprocess) {
00075     delete wireless;
00076     wireless=NULL;
00077     delete kine;
00078     kine=NULL;
00079   }
00080 }
00081 
00082 
00083 void Main::doStart() {
00084 try {
00085   Process::doStart();
00086   //These are constructed by other processes, so need to wait
00087   //until the construction runlevel is complete
00088   sndman->InitAccess(*sounds);
00089   motman->InitAccess(*motions,behaviorLock);
00090   
00091   // initialize output feedback from initial pose loaded by Simulator constructor
00092   if(globals->motion.startPose.size()>0) {
00093     for(unsigned int i=0; i<NumOutputs; ++i)
00094       state->outputs[i]=globals->sensorState.outputs[i];
00095   }
00096 
00097   wireless->listen(sout, config->main.console_port);
00098   wireless->listen(serr, config->main.stderr_port);
00099   wireless_thread.start();
00100   statusrecv=new MessageReceiver(*statusRequest,statusReport);
00101 
00102   if(globals->waitForSensors)
00103     erouter->addListener(this,EventBase::sensorEGID);
00104   evtrecv=new MessageReceiver(*events,gotEvent,false);
00105   visrecv=new MessageReceiver(*cameraFrames,gotCamera,false);
00106   sensrecv=new MessageReceiver(*sensorFrames,gotSensors,false);
00107   timerrecv=new MessageReceiver(*timerWakeup,gotTimer,false);
00108   timerExec=new TimerExecThread(behaviorLock,false);
00109   erouter->serveRemoteEventRequests();
00110   erouter->getEventQueue().spawnCallback(&Main::gotThreadedEvent,*this);
00111 } catch(const std::exception& ex) {
00112   if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Main doStart",&ex))
00113     throw;
00114 } catch(...) {
00115   if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Main doStart",NULL))
00116     throw;
00117 }
00118 }
00119 
00120 void Main::run() {
00121 try {
00122   evtrecv->start();
00123   if(globals->waitForSensors) {
00124     sensrecv->start();
00125     CallbackThread waitSensors(&SharedGlobals::waitSensors,*globals,true);
00126     FailsafeThread failsafe(waitSensors,2.0,true);
00127     waitSensors.join(); // block until either we get the sensors or failsafe cuts in
00128     if(globals->waitForSensors && !globals->haveSensors())
00129       std::cerr << "Blocked on first sensor reading (WaitForSensors is true)... is a driver wedged?" << std::endl;
00130     // block for real now... either user unsets WaitForSensors flag and Simulator sends the signal, or we wait until shut down.
00131     globals->waitSensors();
00132   }
00133 
00134   // might have shutdown triggered while waiting
00135   // (perhaps device isn't available, user's killing the process...)
00136   if(globals->isShutdown())
00137     return; // skip running altogether
00138   
00139   {
00140     MarkScope bl(behaviorLock);
00141     ProjectInterface::startupBehavior().start();
00142     globals->setNextTimer(erouter->getNextTimer());
00143   }
00144   
00145   if(!globals->waitForSensors)
00146     if(!sensrecv->isStarted()) // this could happen if we originally blocked on waitForSensors and then user cleared the configuration flag
00147       sensrecv->start();
00148   visrecv->start();
00149   timerrecv->start();
00150   timerExec->reset();
00151   
00152   {
00153     MarkScope bl(behaviorLock);
00154     erouter->postEvent(EventBase::runtimeEGID,0,EventBase::activateETID);
00155   }
00156   
00157   // this is a bit of a hack, but once we're done launching, display the prompt:
00158   cout << sim::config.cmdPrompt << flush;
00159   
00160   Process::run();
00161 
00162   {
00163     MarkScope bl(behaviorLock);
00164     erouter->postEvent(EventBase::runtimeEGID,0,EventBase::deactivateETID);
00165   }
00166   sensrecv->finish();
00167   visrecv->finish();
00168   evtrecv->finish();
00169   timerrecv->finish();
00170   erouter->getEventQueue().finishCallback();
00171   
00172   {
00173     MarkScope bl(behaviorLock);
00174     ProjectInterface::startupBehavior().stop();
00175     globals->setNextTimer(erouter->getNextTimer());
00176   }
00177   timerExec->reset();
00178 
00179 } catch(const std::exception& ex) {
00180   if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Main 'run' runlevel (startupBehavior initialization and startup)",&ex))
00181     throw;
00182 } catch(...) {
00183   if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Main 'run' runlevel (startupBehavior initialization and startup)",NULL))
00184     throw;
00185 }
00186 }
00187 
00188 void Main::doStop() {
00189 try {
00190 
00191   delete sensrecv;
00192   sensrecv=NULL;
00193   delete visrecv;
00194   visrecv=NULL;
00195   delete evtrecv;
00196   evtrecv=NULL;
00197   delete timerrecv;
00198   timerrecv=NULL;
00199   delete statusrecv;
00200   statusrecv=NULL;
00201   
00202   motman->RemoveAccess();
00203   
00204   if(curimgregion!=NULL)
00205     curimgregion->RemoveReference();
00206 
00207   wireless_thread.stop();
00208   wireless_thread.join();
00209   wireless->setDaemon(sout,false);
00210   wireless->close(sout);
00211   sout=NULL;
00212   wireless->setDaemon(serr,false);
00213   wireless->close(serr);
00214   serr=NULL;
00215   
00216   Process::doStop();
00217 
00218 } catch(const std::exception& ex) {
00219   if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Main doStop",&ex))
00220     throw;
00221 } catch(...) {
00222   if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Main doStop",NULL))
00223     throw;
00224 }
00225 }
00226 
00227 void Main::processEvent(const EventBase&) {
00228   if(state->frameNumber==0)
00229     return; // heartbeats don't count for signalHaveSensors()
00230   erouter->removeListener(this);
00231   for(unsigned int i=0; i<NumOutputs; i++)
00232     motman->setOutput(NULL,i,state->outputs[i]);
00233   globals->signalHaveSensors();
00234 }
00235 
00236 bool Main::gotCamera(RCRegion* msg) {
00237   if(msg==NULL)
00238     return true;
00239   Main * main=dynamic_cast<Main*>(Process::getCurrent());
00240   ASSERTRETVAL(main!=NULL,"gotCamera, but not within Main process!",true);
00241   MarkScope bl(main->behaviorLock);
00242   PROFSECTION("GotImage()",*mainProfiler);
00243 
00244   try {
00245     BufferedImageGenerator::ImageSource& img=main->img;
00246     
00247     DataSource::ImageHeader* header = reinterpret_cast<DataSource::ImageHeader*>(msg->Base());
00248     char* buf=msg->Base()+sizeof(*header);
00249     unsigned int remain=header->width * header->height * header->components;
00250     if(globals->vision.verbose>=1 && header->frameNumber-main->lastVisionSN!=1)
00251       cout << "Main dropped " << (header->frameNumber-main->lastVisionSN-1) << " camera frame(s)" << endl;
00252     main->lastVisionSN=header->frameNumber;
00253     if(globals->vision.verbose>=3 && remain==0)
00254       cout << "Main received image heartbeat at " << get_time() << endl;
00255     else if(globals->vision.verbose>=2 && remain!=0)
00256       cout << "Main received image data \"" << header->name << "\" at " << get_time() << " with source: " << header->sourceID << endl;
00257     
00258     img.frameIndex=header->frameNumber;
00259     if(remain==0) {
00260       if(img.width==0 || img.height==0 || img.img==NULL)
00261         return true; // can't do the heartbeat, don't have an initial image to replicate
00262     } else {
00263       img.width=header->width;
00264       img.height=header->height;
00265       img.channels=header->components;
00266       if(header->layer!=0) {
00267         if(header->layer<0)
00268           img.layer = ProjectInterface::defRawCameraGenerator->getNumLayers()+header->layer;
00269         else
00270           img.layer = header->layer-1; // have ensured layer >=1 due to outer conditional
00271       } else {
00272         // using "automatic" mode, pick the layer closest to resolution of provided image
00273         // assumes each layer doubles in size, with smallest layer at 0
00274         float fullRes=std::sqrt((float)(CameraResolutionX*CameraResolutionY)); // from RobotInfo
00275         float givenRes=std::sqrt((float)(img.width*img.height));
00276         if(givenRes==0) {
00277           cerr << "Main received empty image!" << endl;
00278           return true;
00279         } else {
00280           float ratio=log2f(givenRes/fullRes);
00281           int layerOff=static_cast<int>(rintf(ratio));
00282           int tgtLayer=static_cast<int>(ProjectInterface::fullLayer)+layerOff;
00283           if(tgtLayer<0)
00284             img.layer=0;
00285           else if(ProjectInterface::defRawCameraGenerator!=NULL && static_cast<unsigned int>(tgtLayer)>=ProjectInterface::defRawCameraGenerator->getNumLayers())
00286             img.layer=ProjectInterface::defRawCameraGenerator->getNumLayers()-1;
00287           else
00288             img.layer=tgtLayer;
00289           if(static_cast<unsigned int>(tgtLayer)!=img.layer)
00290             cerr << "Image dimensions of " << img.width << "x" << img.height << " are well beyond the available resolution layers (full is " << CameraResolutionX << "x" << CameraResolutionY << ")" << endl;
00291         }
00292       }
00293       img.img=reinterpret_cast<unsigned char*>(buf);
00294       msg->AddReference();
00295       if(main->curimgregion!=NULL)
00296         main->curimgregion->RemoveReference();
00297       main->curimgregion=msg;
00298     }
00299     DataEvent<BufferedImageGenerator::ImageSource> dev(img,EventBase::visOFbkEGID,header->sourceID,EventBase::activateETID);
00300     erouter->postEvent(dev);
00301     dev.setTypeID(EventBase::statusETID);
00302     erouter->postEvent(dev);
00303     dev.setTypeID(EventBase::deactivateETID);
00304     erouter->postEvent(dev);
00305 
00306   } catch(const std::exception& ex) {
00307     if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during camera frame processing",&ex))
00308       throw;
00309   } catch(...) {
00310     if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during camera frame processing",NULL))
00311       throw;
00312   }
00313   try {
00314     erouter->processTimers();
00315   } catch(const std::exception& ex) {
00316     if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",&ex))
00317       throw;
00318   } catch(...) {
00319     if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",NULL))
00320       throw;
00321   }
00322   if(globals->setNextTimer(erouter->getNextTimer()))
00323     main->timerExec->reset();
00324   return true;
00325 }
00326 
00327 bool Main::gotSensors(RCRegion* /*msg*/) {
00328   Main * main=dynamic_cast<Main*>(Process::getCurrent());
00329   ASSERTRETVAL(main!=NULL,"gotSensors, but not within Main process!",true);
00330 
00331   PROFSECTION("GotSensorFrame()",*mainProfiler);
00332   MarkScope l(main->behaviorLock);
00333 
00334   try {
00335     MarkScope sensorLock(globals->sensorState);
00336     unsigned int frameInc = globals->sensorState.frameNumber - state->frameNumber;
00337     if(frameInc>2 && globals->sensors.verbose>=1)
00338       std::cout << "Main dropped " << (frameInc-1) << " sensor updates... " << std::endl;
00339     if(globals->sensors.verbose>=4)
00340       std::cout << "Processing " << (frameInc==0 && state->frameNumber!=0 ? "duplicate " : "") << "sensor update #" << globals->sensorState.frameNumber << " @" << get_time() << "... ";
00341     state->read(globals->sensorState,true);
00342     if(globals->sensors.verbose>=4)
00343       std::cout << "sensor processing completed @" << get_time() << std::endl;
00344   } catch(const std::exception& ex) {
00345     if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during sensor processing",&ex))
00346       throw;
00347   } catch(...) {
00348     if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during sensor processing",NULL))
00349       throw;
00350   }
00351   
00352   try {
00353     erouter->processTimers();
00354   } catch(const std::exception& ex) {
00355     if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",&ex))
00356       throw;
00357   } catch(...) {
00358     if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",NULL))
00359       throw;
00360   }
00361   if(globals->setNextTimer(erouter->getNextTimer()))
00362     main->timerExec->reset();
00363   return true;
00364 }
00365 
00366 bool Main::gotEvent(RCRegion* msg) {
00367   if(msg==NULL)
00368     return true;
00369   Main * main=dynamic_cast<Main*>(Process::getCurrent());
00370   ASSERTRETVAL(main!=NULL,"gotEvent, but not within Main process!",true);
00371   MarkScope l(main->behaviorLock);
00372   EventBase* evt=NULL;
00373   try {
00374     evt=EventTranslator::decodeEvent(msg->Base(),msg->Size());
00375     if(evt==NULL) {
00376       cerr << "ERROR: Main::gotEvent() failed to decode message" << endl;
00377       return true;
00378     }
00379     erouter->postEvent(*evt);
00380   } catch(const std::exception& ex) {
00381     std::string emsg("Occurred during inter-process event processing");
00382     if(evt!=NULL)
00383       emsg+=": "+evt->getName();
00384     delete evt;
00385     evt=NULL;
00386     if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,emsg.c_str(),&ex))
00387       throw;
00388   } catch(...) {
00389     std::string emsg("Occurred during inter-process event processing");
00390     if(evt!=NULL)
00391       emsg+=": "+evt->getName();
00392     delete evt;
00393     evt=NULL;
00394     if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,emsg.c_str(),NULL))
00395       throw;
00396   }
00397   delete evt;
00398   evt=NULL;
00399   try {
00400     erouter->processTimers();
00401   } catch(const std::exception& ex) {
00402     if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",&ex))
00403       throw;
00404   } catch(...) {
00405     if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",NULL))
00406       throw;
00407   }
00408   if(globals->setNextTimer(erouter->getNextTimer()))
00409     main->timerExec->reset();
00410   return true;
00411 }
00412 
00413 bool Main::gotTimer(RCRegion* /*msg*/) {
00414   Main * main=dynamic_cast<Main*>(Process::getCurrent());
00415   ASSERTRETVAL(main!=NULL,"gotTimer, but not within Main process!",true);
00416 
00417   ASSERTRETVAL(main->timerExec!=NULL,"timerExec thread is NULL when timer wakeup received",true);
00418   main->timerExec->reset();
00419   
00420   if(globals->timeScale<=0) {
00421     MarkScope bl(main->behaviorLock);
00422     try {
00423       erouter->processTimers();
00424     } catch(const std::exception& ex) {
00425       if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",&ex))
00426         throw;
00427     } catch(...) {
00428       if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",NULL))
00429         throw;
00430     }
00431     globals->setNextTimer(erouter->getNextTimer());
00432     // don't need to reset timerExec (again) because we're only here if speed<=0, in which case timerExec isn't running main->timerExec->reset();
00433   }
00434   return true;
00435 }
00436 
00437 void Main::gotThreadedEvent(EventBase* evt) {
00438 #ifdef DEBUG
00439   Main * main=dynamic_cast<Main*>(Process::getCurrent());
00440   ASSERTRET(main!=NULL,"gotThreadedEvent, but not within Main process!");
00441 #endif
00442   // We (the callback) are responsible for deleting this event.
00443   MarkScope l(behaviorLock);
00444   try {
00445     erouter->postEvent(*evt);
00446   } catch(const std::exception& ex) {
00447     std::string emsg("Occurred during queued/inter-thread event processing");
00448     if(evt!=NULL)
00449       emsg+=": "+evt->getName();
00450     delete evt;
00451     evt=NULL;
00452     if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,emsg.c_str(),&ex))
00453       throw;
00454   } catch(...) {
00455     std::string emsg("Occurred during queued/inter-process event processing");
00456     if(evt!=NULL)
00457       emsg+=": "+evt->getName();
00458     delete evt;
00459     evt=NULL;
00460     if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,emsg.c_str(),NULL))
00461       throw;
00462   }
00463   delete evt;
00464   evt=NULL;
00465   try {
00466     erouter->processTimers();
00467   } catch(const std::exception& ex) {
00468     if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",&ex))
00469       throw;
00470   } catch(...) {
00471     if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",NULL))
00472       throw;
00473   }
00474   if(globals->setNextTimer(erouter->getNextTimer()))
00475     timerExec->reset();
00476 }
00477 
00478 /*! @file
00479  * @brief 
00480  * @author ejt (Creator)
00481  */
00482 

Tekkotsu Hardware Abstraction Layer 5.1CVS
Generated Mon May 9 05:01:38 2016 by Doxygen 1.6.3