Homepage Demos Overview Downloads Tutorials Reference
Credits

MMCombo.cc

Go to the documentation of this file.
00001 #include "MMCombo.h"
00002 #include "Shared/WorldState.h"
00003 #include "Shared/Profiler.h"
00004 #include "Shared/debuget.h"
00005 #include "Shared/Config.h"
00006 #include "Shared/SharedObject.h"
00007 #include "Shared/ProcessID.h"
00008 #include "Events/EventRouter.h"
00009 #include "Behaviors/BehaviorBase.h"
00010 #include "Motion/MotionManager.h"
00011 #include "SoundPlay/SoundManager.h"
00012 #include "Vision/Vision.h"
00013 #include "Events/TextMsgEvent.h"
00014 #include "Shared/WMclass.h"
00015 
00016 #include "Shared/ERS210Info.h"
00017 #include "Shared/ERS220Info.h"
00018 
00019 #include <OPENR/OSyslog.h>
00020 #include <OPENR/core_macro.h>
00021 #include <OPENR/OFbkImage.h>
00022 
00023 using namespace std;
00024 
00025 extern BehaviorBase& startupBehavior;
00026 
00027 MMCombo::MMCombo()
00028   : OObject(), motmanMemRgn(NULL), worldStateMemRgn(NULL),
00029     soundManagerMemRgn(NULL), eventTranslatorQueueMemRgn(NULL),
00030     runLevel(0), num_open(0), etrans(), RPOPENR_isready(true), isStopped(true)
00031 {
00032   for(unsigned int i=0; i<NumOutputs; i++) {
00033     primIDs[i]=oprimitiveID_UNDEF;
00034     open[i]=false;
00035   }
00036   Profiler::initBuckets();
00037 }
00038 
00039 
00040 OStatus
00041 MMCombo::DoInit(const OSystemEvent&)
00042 {
00043   isStopped=false;
00044 
00045   NEW_ALL_SUBJECT_AND_OBSERVER;
00046   REGISTER_ALL_ENTRY;
00047   SET_ALL_READY_AND_NOTIFY_ENTRY;
00048     
00049   // make sure the library doesn't drop data "for" us on this reliable communication channel
00050   observer[obsReceiveWorldState]->SetBufCtrlParam(0,1,1);
00051   observer[obsReceiveMotionManager]->SetBufCtrlParam(0,1,1);
00052   observer[obsMotionManagerComm]->SetBufCtrlParam(0,1,MotionManager::MAX_MOTIONS+1);
00053   //+1 to MAX_MOTIONS so we can get a delete message after we've filled up
00054     
00055   //Read config file
00056   config=new Config("/ms/config/tekkotsu.cfg");
00057 
00058   erouter = new EventRouter;
00059 
00060   if(strcmp(objectName,"MainObj")==0) {
00061     ProcessID::setID(ProcessID::MainProcess);
00062 
00063     bool isSlowOutput[NumOutputs];
00064     for(unsigned int i=0; i<NumOutputs; i++)
00065       isSlowOutput[i]=!IsFastOutput[i];
00066 
00067     SetupOutputs(isSlowOutput);
00068 
00069     //Request power status updates
00070     OPowerStatus observationStatus;
00071     observationStatus.Set(orsbALL,obsbALL,opsoREMAINING_CAPACITY_NOTIFY_EVERY_CHANGE,opsoTEMPERATURE_NOTIFY_EVERY_CHANGE,opsoTIME_DIF_NOTIFY_EVERY_CHANGE,opsoVOLUME_NOTIFY_EVERY_CHANGE);
00072     OServiceEntry entry(myOID_, Extra_Entry[entryGotPowerEvent]);
00073     OStatus result = OPENR::ObservePowerStatus(observationStatus, entry);
00074     if(result != oSUCCESS) {
00075       OSYSLOG1((osyslogERROR, "%s : %s %d","MMCombo::DoStart()","OPENR::ObservePowerStatus() FAILED", result));
00076       return oFAIL;
00077     }
00078 
00079     //Setup wireless
00080     wireless = new Wireless();
00081     sout=wireless->socket(SocketNS::SOCK_STREAM,Wireless::WIRELESS_DEF_RECV_SIZE,Wireless::WIRELESS_DEF_SEND_SIZE*6);
00082     serr=wireless->socket(SocketNS::SOCK_STREAM,Wireless::WIRELESS_DEF_RECV_SIZE,Wireless::WIRELESS_DEF_SEND_SIZE*2);
00083     wireless->setDaemon(sout);
00084     wireless->setDaemon(serr);
00085     serr->setFlushType(SocketNS::FLUSH_BLOCKING);
00086     sout->setTextForward();
00087     serr->setForward(sout);
00088 
00089     //worldStateMemRgn -> state setup
00090     worldStateMemRgn = InitRegion(sizeof(WorldState));
00091     state=new ((WorldState*)worldStateMemRgn->Base()) WorldState;
00092 
00093     //eventTranslatorQueueMemRgn -> etrans setup
00094     eventTranslatorQueueMemRgn = InitRegion(sizeof(EventTranslator::Queue_t));
00095     EventTranslator::Queue_t * etransq=new ((EventTranslator::Queue_t*)eventTranslatorQueueMemRgn->Base()) EventTranslator::Queue_t;
00096     etrans.setQueue(etransq);
00097     MotionCommand::setQueue(etransq);
00098 
00099     //Setup vision
00100     vision=new Vision();
00101     // someday these will go away:
00102     vision->enableEvents(VisionEventNS::PinkBallSID);
00103     vision->enableEvents(VisionEventNS::RedBallSID);
00104     vision->enableEvents(VisionEventNS::MarkersSID);
00105   
00106   }
00107   if(strcmp(objectName,"MotoObj")==0) {
00108     ProcessID::setID(ProcessID::MotionProcess);
00109 
00110     SetupOutputs(IsFastOutput);
00111     OPENR::SetMotorPower(opowerON);
00112     OPENR::EnableJointGain(oprimitiveID_UNDEF); //oprimitiveID_UNDEF means enable all
00113 
00114     //motmanMemRgn -> motman setup
00115     motmanMemRgn = InitRegion(sizeof(MotionManager));
00116     motman = new (motmanMemRgn->Base()) MotionManager();
00117     motman->InitAccess(subject[sbjMotionManagerComm]);
00118   }
00119   startupBehavior.AddReference();
00120   return oSUCCESS;
00121 }
00122 
00123 OStatus
00124 MMCombo::DoStart(const OSystemEvent&)
00125 {
00126   //  cout << objectName << "::DoStart() " << endl;
00127 
00128   // initialize the current power status, doesn't always give us
00129   // a power update right away otherwise
00130   if(strcmp(objectName,"MainObj")==0) {
00131     wireless->listen(sout, config->main.console_port);
00132     wireless->listen(serr, config->main.stderr_port);
00133     OPowerStatus power;
00134     OPENR::GetPowerStatus(&power);
00135     state->read(power,erouter);
00136   }
00137 
00138   isStopped=false;
00139 
00140   ENABLE_ALL_SUBJECT;
00141   ASSERT_READY_TO_ALL_OBSERVER;
00142 
00143   addRunLevel();
00144   
00145   return oSUCCESS;
00146 }
00147 
00148 OStatus
00149 MMCombo::DoStop(const OSystemEvent&)
00150 {
00151   cout << objectName << "::DoStop()..." << endl;
00152   if(strcmp(objectName,"MainObj")==0) {
00153     startupBehavior.DoStop();
00154     wireless->close(sout);
00155     wireless->close(serr);
00156   }
00157   DISABLE_ALL_SUBJECT;
00158   DEASSERT_READY_TO_ALL_OBSERVER;
00159   isStopped=true;
00160   cout << objectName << "::DoStop()-DONE" << endl;
00161   return oSUCCESS;
00162 }
00163 
00164 OStatus
00165 MMCombo::DoDestroy(const OSystemEvent&)
00166 {
00167   cout << objectName << "::DoDestroy()..." << endl;
00168   startupBehavior.RemoveReference();
00169   if(strcmp(objectName,"MainObj")==0) {
00170     delete erouter;
00171     motmanMemRgn->RemoveReference();
00172   }
00173   if(strcmp(objectName,"MotoObj")==0) {
00174     worldStateMemRgn->RemoveReference();
00175     eventTranslatorQueueMemRgn->RemoveReference();
00176   }
00177   soundManagerMemRgn->RemoveReference();
00178   DELETE_ALL_SUBJECT_AND_OBSERVER;
00179   cout << objectName << "::DoDestroy()-DONE" << endl;
00180   return oSUCCESS;
00181 }
00182 
00183 /*! Called when MotoObj is initially ready as well as when it has finished
00184  *  processing the previous message - we only want to do this the first time
00185  *  otherwise we infinite loop. */
00186 void
00187 MMCombo::ReadyRegisterWorldState(const OReadyEvent&){
00188   static bool is_init=true;
00189   if(is_init) {
00190     is_init=false;
00191     cout << objectName << " Registering WorldState" << endl;
00192     if(strcmp(objectName,"MainObj")==0) {
00193       subject[sbjRegisterWorldState]->SetData(worldStateMemRgn);
00194       subject[sbjRegisterWorldState]->NotifyObservers();
00195     }
00196   }
00197 }
00198 
00199 void
00200 MMCombo::GotWorldState(const ONotifyEvent& event){
00201   cout << objectName << "-GOTWORLDSTATE..." << flush;
00202   //  PROFSECTION("GotMemRegion()",state->mainProfile);
00203   if(strcmp(objectName,"MotoObj")==0) {
00204     ASSERT(event.NumOfData()==1,"Too many WorldStates");
00205     worldStateMemRgn = event.RCData(0);
00206     worldStateMemRgn->AddReference();
00207     state = reinterpret_cast<WorldState*>(worldStateMemRgn->Base());
00208   }
00209   observer[obsReceiveWorldState]->AssertReady();
00210   cout << "done" << endl;
00211 }
00212 
00213     
00214 /*! Called when MainObj is initially ready as well as when it has finished
00215  *  processing the previous message - we only want to do this the first time
00216  *  otherwise we infinite loop. */
00217 void
00218 MMCombo::ReadyRegisterMotionManager(const OReadyEvent&){
00219   static bool is_init=true;
00220   if(is_init) {
00221     is_init=false;
00222     cout << objectName << " Registering MotionManager" << endl;
00223     if(strcmp(objectName,"MotoObj")==0) {
00224       subject[sbjRegisterMotionManager]->SetData(motmanMemRgn);
00225       subject[sbjRegisterMotionManager]->NotifyObservers();
00226     }
00227   }
00228 }
00229 
00230 void
00231 MMCombo::GotMotionManager(const ONotifyEvent& event){
00232   cout << objectName << "-GOTWORLDSTATE..." << flush;
00233   //  PROFSECTION("GotMemRegion()",state->motoProfile);
00234   if(strcmp(objectName,"MainObj")==0) {
00235     ASSERT(event.NumOfData()==1,"Too many MotionManagers");
00236     motmanMemRgn = event.RCData(0);
00237     motmanMemRgn->AddReference();
00238     motman = reinterpret_cast<MotionManager*>(motmanMemRgn->Base());
00239     cout << "MAIN INIT MOTMAN..." << flush;
00240     //      hexout(event.RCData(event_data_id)->Base(),128);
00241     motman->InitAccess(subject[sbjMotionManagerComm]);
00242     addRunLevel();
00243   }
00244   observer[obsReceiveMotionManager]->AssertReady();
00245   cout << "done" << endl;
00246 }
00247 
00248 /*! Called when MotoObj is initially ready as well as when it has finished
00249  *  processing the previous message - we only want to do this the first time
00250  *  otherwise we infinite loop. */
00251 void
00252 MMCombo::ReadyRegisterEventTranslatorQueue(const OReadyEvent&){
00253   static bool is_init=true;
00254   if(is_init) {
00255     is_init=false;
00256     cout << objectName << " Registering EventTranslatorQueue" << endl;
00257     if(strcmp(objectName,"MainObj")==0) {
00258       subject[sbjRegisterEventTranslatorQueue]->SetData(eventTranslatorQueueMemRgn);
00259       subject[sbjRegisterEventTranslatorQueue]->NotifyObservers();
00260     }
00261   }
00262 }
00263 
00264 void
00265 MMCombo::GotEventTranslatorQueue(const ONotifyEvent& event){
00266   cout << objectName << "-GOTEventTranslatorQueue..." << flush;
00267   //  PROFSECTION("GotMemRegion()",state->mainProfile);
00268   if(strcmp(objectName,"MotoObj")==0) {
00269     ASSERT(event.NumOfData()==1,"Too many EventTranslatorQueue");
00270     eventTranslatorQueueMemRgn = event.RCData(0);
00271     eventTranslatorQueueMemRgn->AddReference();
00272     EventTranslator::Queue_t * etransq=reinterpret_cast<EventTranslator::Queue_t*>(eventTranslatorQueueMemRgn->Base());
00273     etrans.setQueue(etransq);
00274     MotionCommand::setQueue(etransq);
00275     erouter->addTrapper(&etrans);
00276   }
00277   observer[obsReceiveEventTranslatorQueue]->AssertReady();
00278   cout << "done" << endl;
00279 }
00280 
00281     
00282 void
00283 MMCombo::ReadySendJoints(const OReadyEvent& sysevent) {
00284 
00285   if(isStopped) {
00286     //cout << "BAH!ReadySendJoints" << endl;
00287     return;
00288   }
00289 
00290   static unsigned int id=-1U;
00291   Profiler::Timer timer;
00292   if(ProcessID::getID()==ProcessID::MotionProcess) {
00293     if(state) {
00294       if(id==-1U)
00295         id=state->motionProfile.getNewID("ReadySendJoints()");
00296       timer.setID(id,&state->motionProfile);
00297     }
00298   } else if(ProcessID::getID()==ProcessID::MainProcess) {
00299     if(id==-1U)
00300       id=state->mainProfile.getNewID("ReadySendJoints()");
00301     timer.setID(id,&state->mainProfile);
00302   }
00303 
00304   if(num_open==0) //If we don't have any joints to open, leave now. (i.e. MainObj on a 220, has no ears)
00305     return;
00306 
00307   // Find an unused command vector
00308   RCRegion* rgn=NULL;
00309   for (unsigned int i = 0; i < NUM_COMMAND_VECTOR; i++) {
00310     if (region[i]->NumberOfReference() == 1) {
00311       rgn=region[i];
00312       /*      if(strcmp(objectName,"MainObj")==0) {
00313               static unsigned int lasttime=get_time();
00314               unsigned int thistime=get_time();
00315               cout << '*' << i << ' ' << thistime << '\t' << (thistime-lasttime) << endl;
00316               lasttime=thistime;
00317               }*/
00318       break;
00319     }
00320   }
00321   ASSERTRET(rgn!=NULL,"Could not find unused command vector");
00322   ASSERTRET(rgn->Base()!=NULL,"Bad Command Vector");
00323   OCommandVectorData* cmdVecData = reinterpret_cast<OCommandVectorData*>(rgn->Base());
00324   
00325   // Update the outputs (note that Main is doing the ears)
00326   //I'm using an id compare instead of the slightly more readable strcmp for a tiny bit of speed
00327   if(ProcessID::getID()==ProcessID::MotionProcess) {
00328     float outputs[NumFrames][NumOutputs];
00329     if(state!=NULL) {
00330       motman->getOutputs(outputs);
00331       motman->updatePIDs(primIDs);
00332       motman->updateWorldState();
00333     } else {
00334       for(unsigned int f=0; f<NumFrames; f++)
00335         for(unsigned int i=0; i<NumOutputs; i++)
00336           outputs[f][i]=0;
00337     }
00338 
00339     // Should be a relatively simple matter to copy angles into commands...
00340     unsigned int used=0; //but only copy open joints (so main does ears, motion does everything else)
00341     for(unsigned int i=PIDJointOffset; i<PIDJointOffset+NumPIDJoints; i++)
00342       if(open[i]) {
00343         OJointCommandValue2* jval = reinterpret_cast<OJointCommandValue2*>(cmdVecData->GetData(used)->value);
00344         for(unsigned int frame=0; frame<NumFrames; frame++)
00345           jval[frame].value = (slongword)(outputs[frame][i]*1e6);
00346         used++;
00347       }
00348     for(unsigned int i=LEDOffset; i<LEDOffset+NumLEDs; i++)
00349       if(open[i]) {
00350         OLEDCommandValue2* jval = reinterpret_cast<OLEDCommandValue2*>(cmdVecData->GetData(used)->value);
00351         for(unsigned int frame=0; frame<NumFrames; frame++)
00352           jval[frame].led = calcLEDValue(i-LEDOffset,outputs[frame][i]);
00353         used++;
00354       }
00355     for(unsigned int i=BinJointOffset; i<BinJointOffset+NumBinJoints; i++)
00356       if(open[i]) {
00357         OJointCommandValue3* jval = reinterpret_cast<OJointCommandValue3*>(cmdVecData->GetData(used)->value);
00358         for(unsigned int frame=0; frame<NumSlowFrames; frame++)
00359           jval[frame].value = (outputs[frame][i]<.5?ojoint3_STATE1:ojoint3_STATE0);
00360         used++;
00361       }
00362   } else if(ProcessID::getID()==ProcessID::MainProcess) {
00363     // Just copy over the current ear state from WorldState in case this is in Main
00364     unsigned int used=0; //but only copy open joints (so main does ears, motion does everything else)
00365     for(unsigned int i=BinJointOffset; i<BinJointOffset+NumBinJoints; i++)
00366       if(open[i]) {
00367         OJointCommandValue3* jval = reinterpret_cast<OJointCommandValue3*>(cmdVecData->GetData(used)->value);
00368         for(unsigned int frame=0; frame<NumSlowFrames; frame++)
00369           jval[frame].value = (state->outputs[i]<.5?ojoint3_STATE1:ojoint3_STATE0);
00370         used++;
00371       }
00372   }
00373 
00374   // Send outputs to system
00375   subject[sbjMoveJoint]->SetData(rgn);
00376 
00377   // The first time this is called, we actually need to send *two* buffers
00378   // in order to get the double buffering going... (well, actually generalized
00379   // for NUM_COMMAND_VECTOR level buffering)
00380   static unsigned int initCount=1;
00381   if(initCount<NUM_COMMAND_VECTOR) {
00382     initCount++;
00383     ReadySendJoints(sysevent);
00384   } else //recursive base case
00385     subject[sbjMoveJoint]->NotifyObservers();
00386 }
00387 
00388 void
00389 MMCombo::GotSensorFrame(const ONotifyEvent& event){
00390   //  if(state && state->buttons[RFrPawOffset])
00391   //  cout << "SENSOR..."<<flush;
00392   if(isStopped) {
00393     //cout << "BAH!GotSensorFrame" << endl;
00394     return;
00395   }
00396 
00397   PROFSECTION("GotSensorFrame()",state->mainProfile);
00398   etrans.translateEvents();
00399 
00400   OSensorFrameVectorData* rawsensor = reinterpret_cast<OSensorFrameVectorData*>(event.RCData(0)->Base());
00401   state->read(rawsensor[0],erouter);
00402   erouter->processTimers();
00403   static unsigned int throwaway=1; //i thought the first few sensor updates might be flakey, but now i think not.  But a good way to delay startup.
00404   if(throwaway!=0) {
00405     throwaway--;
00406     if(throwaway==0)
00407       addRunLevel();
00408   }
00409   observer[obsSensorFrame]->AssertReady();
00410   if (state!=NULL && state->wsser!=NULL)
00411     state->wsser->serialize();
00412   //  if(state && state->buttons[RFrPawOffset])
00413   //  cout << "done" << endl;
00414 }
00415 
00416 void
00417 MMCombo::GotImage(const ONotifyEvent& event){
00418   if(isStopped) {
00419     //cout << "BAH!GotImage" << endl;
00420     return;
00421   }
00422 
00423   PROFSECTION("GotImage()",state->mainProfile);
00424   etrans.translateEvents();
00425 
00426   if (vision!=NULL) {
00427     const OFbkImageVectorData *fbkImageVectorData=reinterpret_cast<const OFbkImageVectorData*>(event.Data(0));
00428     OFbkImageInfo* info = const_cast<OFbkImageVectorData*>(fbkImageVectorData)->GetInfo(vision->imageLayer);
00429     const byte* dat = const_cast<OFbkImageVectorData*>(fbkImageVectorData)->GetData(vision->imageLayer);
00430     const OFbkImage yimage(info, const_cast<byte*>(dat), ofbkimageBAND_Y);
00431     const OFbkImage uimage(info, const_cast<byte*>(dat), ofbkimageBAND_Cr);
00432     const OFbkImage vimage(info, const_cast<byte*>(dat), ofbkimageBAND_Cb);
00433 
00434     const byte* bytes_y = yimage.Pointer();
00435     const byte* bytes_u = uimage.Pointer();
00436     const byte* bytes_v = vimage.Pointer();
00437 
00438     int width  = yimage.Width();
00439     int height = yimage.Height();
00440 
00441     WMvari(int, frame_counter, 0);
00442     ++frame_counter;
00443     vision->processFrame(bytes_y, bytes_u, bytes_v, width, height, yimage.Skip());
00444   }
00445   erouter->processTimers();
00446   
00447   observer[obsImage]->AssertReady();
00448 }
00449 
00450 void
00451 MMCombo::GotPowerEvent(void * msg){
00452   if(isStopped) {
00453     //cout << "BAH!GotPowerEvent" << endl;
00454     return;
00455   }
00456 
00457   //  cout << "POWER..."<<flush;
00458   PROFSECTION("PowerEvent()",state->mainProfile);
00459   etrans.translateEvents();
00460 
00461   static bool first=true;
00462   if(first) {
00463     addRunLevel();
00464     first=false;
00465   }
00466   const OPowerStatus* result = &static_cast<OPowerStatusMessage*>(msg)->powerStatus;
00467   state->read(*result,erouter);
00468   erouter->processTimers();
00469   // this part watches to see if the power button is pressed to shutdown the robot
00470   // i'm leaving this low-level because there's not much else you can do anyway...
00471   // the hardware kills power to the motors, and as far as we can tell, you can't
00472   // turn them back on.
00473   if(state->powerFlags[PowerSourceID::PauseSID]) {
00474     cout << "%%%%%%%  Pause button was pushed! %%%%%%%" << endl;
00475     OBootCondition bc(0);
00476     OPENR::Shutdown(bc);
00477   }
00478   //  cout << "done" << endl;
00479 }
00480 
00481 void
00482 MMCombo::GotMotionMsg(const ONotifyEvent& event){
00483   if(isStopped) {
00484     //cout << "BAH!GotMotionMsg" << endl;
00485     return;
00486   }
00487 
00488   //  cout << "RECEIVE..."<<flush;
00489   if(motman!=NULL)
00490     motman->receivedMsg(event);
00491   else
00492     cout << "*** WARNING Main dropping MotionCommand (motman not ready) " << endl;
00493   observer[obsMotionManagerComm]->AssertReady();
00494   //  cout << "done" << endl;
00495 }
00496 
00497 void
00498 MMCombo::GotSoundManager(const ONotifyEvent& event) {
00499   cout << objectName << "-GOTSOUNDMANAGER..." << flush;
00500   //  PROFSECTION("GotMemRegion()",state->mainProfile);
00501   ASSERT(event.NumOfData()==1,"Too many SoundManagers");
00502   soundManagerMemRgn = event.RCData(0);
00503   soundManagerMemRgn->AddReference();
00504   sndman = reinterpret_cast<SoundManager*>(soundManagerMemRgn->Base());
00505   observer[obsReceiveSoundManager]->AssertReady();
00506   sndman->InitAccess(subject[sbjSoundManagerComm]);
00507   addRunLevel();
00508   cout << "done" << endl;
00509 }
00510 
00511 void
00512 MMCombo::OpenPrimitives()
00513 {
00514   for(unsigned int i=0; i<NumOutputs; i++)
00515     if(open[i]) {
00516       OStatus result = OPENR::OpenPrimitive(PrimitiveName[i], &primIDs[i]);
00517       if (result != oSUCCESS)
00518         OSYSLOG1((osyslogERROR, "%s : %s %d","MMCombo::DoInit()","OPENR::OpenPrimitive() FAILED", result));
00519     }
00520 }
00521 
00522 void
00523 MMCombo::SetupOutputs(const bool to_open[NumOutputs])
00524 {
00525   char robotDesignStr[orobotdesignNAME_MAX];
00526   memset(robotDesignStr, 0, sizeof(robotDesignStr));
00527   if (OPENR::GetRobotDesign(robotDesignStr) != oSUCCESS) {
00528     cout << objectName << "::SetupOutputs - OPENR::GetRobotDesign() failed." << endl;
00529     return;
00530   } else {
00531     if(strcmp(robotDesignStr,"ERS-210")==0) {
00532       for(unsigned int j=0; j<NumOutputs; j++)
00533         open[j]=to_open[j] && ERS210Info::IsRealERS210[j];
00534     } else if(strcmp(robotDesignStr,"ERS-220")==0) {
00535       for(unsigned int j=0; j<NumOutputs; j++)
00536         open[j]=to_open[j] && ERS220Info::IsRealERS220[j];
00537     } else {
00538       cout << "MMCombo::SetupOutputs - ERROR: Unrecognized model: "<<robotDesignStr<<"\nSorry..."<<endl;
00539       return;
00540     }
00541   }
00542   
00543   // count how many we're opening
00544   for(unsigned int j=0; j<NumOutputs; j++)
00545     if(open[j])
00546       num_open++;
00547 
00548   if(num_open==0) //If we don't have any joints to open, leave now. (i.e. MainObj on a 220, has no ears)
00549     return;
00550 
00551   OpenPrimitives();
00552 
00553   OStatus result;
00554   MemoryRegionID      cmdVecDataID;
00555   OCommandVectorData* cmdVecData;
00556 
00557   // request memory regions
00558   for (unsigned int i = 0; i < NUM_COMMAND_VECTOR; i++) {
00559     result = OPENR::NewCommandVectorData(num_open,&cmdVecDataID,&cmdVecData);
00560     if (result != oSUCCESS)
00561       OSYSLOG1((osyslogERROR, "%s : %s %d","MMCombo::NewCommandVectorData()","OPENR::NewCommandVectorData() FAILED", result));
00562     region[i] = new RCRegion(cmdVecData->vectorInfo.memRegionID,cmdVecData->vectorInfo.offset,(void*)cmdVecData,cmdVecData->vectorInfo.totalSize);
00563     cmdVecData->SetNumData(num_open);
00564 
00565     // initialize the outputs we just opened
00566     unsigned int used=0;
00567     ASSERT(cmdVecData==reinterpret_cast<OCommandVectorData*>(region[i]->Base())," should be equal!?");
00568     for(unsigned int j=PIDJointOffset; j<PIDJointOffset+NumPIDJoints; j++)
00569       if(open[j]) {
00570         OCommandInfo* info = cmdVecData->GetInfo(used++);
00571         info->Set(odataJOINT_COMMAND2, primIDs[j], NumFrames);
00572       }
00573     for(unsigned int j=LEDOffset; j<LEDOffset+NumLEDs; j++)
00574       if(open[j]) {
00575         OCommandInfo* info = cmdVecData->GetInfo(used);
00576         info->Set(odataLED_COMMAND2, primIDs[j], NumFrames);
00577         OLEDCommandValue2* jval = reinterpret_cast<OLEDCommandValue2*>(cmdVecData->GetData(used)->value);
00578         for(unsigned int frame=0; frame<NumFrames; frame++)
00579           jval[frame].period = 1;
00580         used++;
00581       }     
00582     for(unsigned int j=BinJointOffset; j<BinJointOffset+NumBinJoints; j++)
00583       if(open[j]) {
00584         OCommandInfo* info = cmdVecData->GetInfo(used++);
00585         info->Set(odataJOINT_COMMAND3, primIDs[j], NumSlowFrames);
00586       }     
00587   }
00588 }
00589 
00590 /*! Will round up size to the nearest page */
00591 RCRegion*
00592 MMCombo::InitRegion(unsigned int size) {
00593   unsigned int pagesize=4096;
00594   sError err=GetPageSize(&pagesize);
00595   ASSERT(err==sSUCCESS,"Error "<<err<<" getting page size");
00596   unsigned int pages=(size+pagesize-1)/pagesize;
00597   return new RCRegion(pages*pagesize);
00598 }
00599 
00600 void
00601 MMCombo::addRunLevel() {
00602   runLevel++;
00603   if(runLevel==readyLevel) {
00604     cout << "START UP BEHAVIOR..." << flush;
00605     startupBehavior.DoStart();
00606     cout << "START UP BEHAVIOR-DONE" << endl;
00607   }
00608 }
00609 
00610 void
00611 MMCombo::RPOPENR_notify(const ONotifyEvent& event) {
00612   const char *buf = (const char *)event.Data(0);
00613   observer[event.ObsIndex()]->AssertReady();
00614 
00615   /* usercode: message received
00616    * an example could be- */
00617   // RPOPENR_send("yeah i received your message", 29);
00618 
00619   /* create TextMsg event which can contain strings
00620    * comment this out if you want to handle the received data exclusively
00621    */
00622   erouter->postEvent(new TextMsgEvent(buf));
00623 }
00624 
00625 int
00626 MMCombo::RPOPENR_send(char *buf, int bufsize) {
00627   if (RPOPENR_isready && bufsize>0) {
00628     RPOPENR_isready=false;
00629     subject[sbjRPOPENRSendString]->SetData(buf, bufsize);
00630     subject[sbjRPOPENRSendString]->NotifyObservers();
00631     return bufsize;
00632   }
00633   return 0;
00634 }
00635 
00636 /*! @file
00637  * @brief Implements MMCombo, the OObject which "forks" (sort of) into Main and Motion processes
00638  * @author ejt (Creator)
00639  *
00640  * $Author: ejt $
00641  * $Name: tekkotsu-1_5 $
00642  * $Revision: 1.40 $
00643  * $State: Rel $
00644  * $Date: 2003/10/10 05:38:21 $
00645  */
00646 
00647 

Tekkotsu v1.5
Generated Fri Oct 10 15:51:59 2003 by Doxygen 1.3.4