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
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
00065 ASSERT(kine==NULL,"global kine already initialized before Main?");
00066 kine=new Kinematics();
00067 }
00068 wireless->setCallbackLock(behaviorLock);
00069
00070
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
00087
00088 sndman->InitAccess(*sounds);
00089 motman->InitAccess(*motions,behaviorLock);
00090
00091
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();
00128 if(globals->waitForSensors && !globals->haveSensors())
00129 std::cerr << "Blocked on first sensor reading (WaitForSensors is true)... is a driver wedged?" << std::endl;
00130
00131 globals->waitSensors();
00132 }
00133
00134
00135
00136 if(globals->isShutdown())
00137 return;
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())
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
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;
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;
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;
00271 } else {
00272
00273
00274 float fullRes=std::sqrt((float)(CameraResolutionX*CameraResolutionY));
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* ) {
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* ) {
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
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
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
00479
00480
00481
00482