Homepage Demos Overview Downloads Tutorials Reference
Credits

MotionManager.cc

Go to the documentation of this file.
00001 #include "MotionManager.h"
00002 #include "Shared/debuget.h"
00003 #include "Shared/WorldState.h"
00004 #include "Events/EventRouter.h"
00005 
00006 #include "Shared/ERS210Info.h"
00007 #include "Shared/ERS220Info.h"
00008 
00009 #include <list>
00010 
00011 MotionManager * motman=NULL;
00012 int MotionManager::_MMaccID=-1U;
00013 
00014 const float MotionManager::kIgnoredPriority    =-1;
00015 const float MotionManager::kBackgroundPriority = 0;
00016 const float MotionManager::kLowPriority        = 5;
00017 const float MotionManager::kStdPriority        = 10;
00018 const float MotionManager::kHighPriority       = 50;
00019 const float MotionManager::kEmergencyPriority  = 100;
00020 
00021 #ifndef PLATFORM_APERIOS
00022 using std::cout;
00023 using std::endl;
00024 #endif
00025 
00026 
00027 //! just for convenience
00028 typedef unsigned int uint;
00029 
00030 MotionManager::MotionManager()
00031   : pidchanges(),cmdlist(),cur_cmd(invalid_MC_ID),MMlock()
00032 #ifdef PLATFORM_APERIOS
00033   ,numAcc(0)
00034 #endif
00035 {
00036   for(uint x=0; x<NumOutputs; x++)
00037     cmdSums[x]=0;
00038 }
00039 
00040 #ifdef PLATFORM_APERIOS
00041 
00042 void
00043 MotionManager::InitAccess(OSubject* subj) {
00044   if(numAcc==MAX_ACCESS) {
00045     printf("*** ERROR *** attempted to register more accessors with MotionManager than allowed by MAX_ACCESS\n");
00046     return;
00047   }
00048   _MMaccID=numAcc++;
00049   //  cout << "ID is now " << _MMaccID << " of " << numAcc << endl;
00050   //  cout << "_MMaccID is " << &_MMaccID << endl;
00051   //  cout << "numAcc is " << &numAcc << " from " << this << endl;
00052   MMlock.lock(_MMaccID);
00053   //  accRegs[accID].init();
00054   subjs[_MMaccID]=subj;
00055   if(cmdlist.size()>0) //Shouldn't happen - busy wait in addMotion
00056     cout << "*** WARNING *** MOTIONS ADDED BEFORE ALL INITACCESSED" << endl;
00057   MMlock.release();
00058 }
00059 
00060 #endif //PLATFORM_APERIOS
00061 
00062 void
00063 MotionManager::setOutput(const MotionCommand* caller, unsigned int output, const OutputCmd& cmd) {
00064     if (output >= NumOutputs) return; 
00065 
00066   if(caller==NULL || caller->getID()!=cur_cmd)
00067     func_begin();
00068   if(cur_cmd==invalid_MC_ID) {
00069     if(cmd.weight>0)
00070       cmdSums[output]=cmd.value;
00071   } else if(getPriority(cur_cmd)>=kBackgroundPriority) {
00072     cmdstatelist_t& curstatelist=cmdstates[output];
00073     cmdstatelist_t::index_t ent=curstatelist.begin();
00074     if(ent==curstatelist.end() || curstatelist[ent].mcid!=cur_cmd)
00075       curstatelist.push_front(OutputState(output,getPriority(cur_cmd),cur_cmd,cmd));
00076     else
00077       for(unsigned int i=0; i<NumFrames; i++)
00078         curstatelist[ent].frames[i]=cmd;
00079   }
00080   if(caller==NULL || caller->getID()!=cur_cmd)
00081     func_end();
00082 }
00083 
00084 void
00085 MotionManager::setOutput(const MotionCommand* caller, unsigned int output, const OutputCmd& cmd, unsigned int frame) {
00086     if (output >= NumOutputs) return; 
00087 
00088   if(caller==NULL || caller->getID()!=cur_cmd)
00089     func_begin();
00090   if(cur_cmd==invalid_MC_ID) {
00091     if(cmd.weight>0)
00092       cmdSums[output]=cmd.value;
00093   } else if(getPriority(cur_cmd)>=kBackgroundPriority) {
00094     cmdstatelist_t& curstatelist=cmdstates[output];
00095     cmdstatelist_t::index_t ent=curstatelist.begin();
00096     if(ent==curstatelist.end() || curstatelist[ent].mcid!=cur_cmd)
00097       curstatelist.push_front(OutputState(output,getPriority(cur_cmd),cur_cmd,cmd,frame));
00098     else
00099       curstatelist[ent].frames[frame]=cmd;
00100   }
00101   if(caller==NULL || caller->getID()!=cur_cmd)
00102     func_end();
00103 }
00104 
00105 void 
00106 MotionManager::setOutput(const MotionCommand* caller, unsigned int output, const OutputCmd ocmds[NumFrames]) {
00107     if (output >= NumOutputs) return; 
00108 
00109   if(caller==NULL || caller->getID()!=cur_cmd)
00110     func_begin();
00111   if(cur_cmd==invalid_MC_ID) {
00112     if(ocmds[NumFrames-1].weight>0)
00113       cmdSums[output]=ocmds[NumFrames-1].value;
00114   } else if(getPriority(cur_cmd)>=kBackgroundPriority) {
00115     cmdstatelist_t& curstatelist=cmdstates[output];
00116     cmdstatelist_t::index_t ent=curstatelist.begin();
00117     if(ent==curstatelist.end() || curstatelist[ent].mcid!=cur_cmd)
00118       curstatelist.push_front(OutputState(output,getPriority(cur_cmd),cur_cmd,ocmds));
00119     else
00120       for(unsigned int i=0; i<NumFrames; i++)
00121         curstatelist[ent].frames[i]=ocmds[i];
00122   }
00123   if(caller==NULL || caller->getID()!=cur_cmd)
00124     func_end();
00125 }
00126 
00127 void
00128 MotionManager::setOutput(const MotionCommand* caller, unsigned int output, const OutputPID& pid) {
00129     if (output >= NumOutputs) return; 
00130 
00131   if(caller==NULL || caller->getID()!=cur_cmd)
00132     func_begin();
00133   if(cur_cmd==invalid_MC_ID) {
00134     //!@todo should be able to set background pid
00135   } else if(getPriority(cur_cmd)>=kBackgroundPriority) {
00136     cmdstatelist_t& curstatelist=cmdstates[output];
00137     cmdstatelist_t::index_t ent=curstatelist.begin();
00138     if(ent==curstatelist.end() || curstatelist[ent].mcid!=cur_cmd)
00139       curstatelist.push_front(OutputState(output,getPriority(cur_cmd),cur_cmd,pid));
00140     else
00141       curstatelist[ent].pid=pid;
00142   }
00143   if(caller==NULL || caller->getID()!=cur_cmd)
00144     func_end();
00145 }
00146 
00147 void
00148 MotionManager::setOutput(const MotionCommand* caller, unsigned int output, const OutputCmd& cmd, const OutputPID& pid) {
00149     if (output >= NumOutputs) return; 
00150 
00151   if(caller==NULL || caller->getID()!=cur_cmd)
00152     func_begin();
00153   if(cur_cmd==invalid_MC_ID) {
00154     if(cmd.weight>0)
00155       cmdSums[output]=cmd.value;
00156   } else if(getPriority(cur_cmd)>=kBackgroundPriority) {
00157     cmdstatelist_t& curstatelist=cmdstates[output];
00158     cmdstatelist_t::index_t ent=curstatelist.begin();
00159     if(ent==curstatelist.end() || curstatelist[ent].mcid!=cur_cmd)
00160       curstatelist.push_front(OutputState(output,getPriority(cur_cmd),cur_cmd,cmd,pid));
00161     else {
00162       for(unsigned int i=0; i<NumFrames; i++)
00163         curstatelist[ent].frames[i]=cmd;
00164       curstatelist[ent].pid=pid;
00165     }
00166   }
00167   if(caller==NULL || caller->getID()!=cur_cmd)
00168     func_end();
00169 }
00170 
00171 void
00172 MotionManager::setOutput(const MotionCommand* caller, unsigned int output, const OutputCmd ocmds[NumFrames], const OutputPID& pid) {
00173     if (output >= NumOutputs) return; 
00174 
00175   if(caller==NULL || caller->getID()!=cur_cmd)
00176     func_begin();
00177   if(cur_cmd==invalid_MC_ID) {
00178     if(ocmds[NumFrames-1].weight>0)
00179       cmdSums[output]=ocmds[NumFrames-1].value;
00180   } else if(getPriority(cur_cmd)>=kBackgroundPriority) {
00181     cmdstatelist_t& curstatelist=cmdstates[output];
00182     cmdstatelist_t::index_t ent=curstatelist.begin();
00183     if(ent==curstatelist.end() || curstatelist[ent].mcid!=cur_cmd)
00184       curstatelist.push_front(OutputState(output,getPriority(cur_cmd),cur_cmd,ocmds));
00185     else {
00186       for(unsigned int i=0; i<NumFrames; i++)
00187         curstatelist[ent].frames[i]=ocmds[i];
00188       curstatelist[ent].pid=pid;
00189     }
00190   }
00191   if(caller==NULL || caller->getID()!=cur_cmd)
00192     func_end();
00193 }
00194 
00195 /*! What's worse? A plethora of functions which are only called, and only useful at one place,
00196  *  or a big massive function which doesn't pollute the namespace?  This is the latter, for
00197  *  better or worse. */
00198 void
00199 MotionManager::getOutputs(float outputs[NumFrames][NumOutputs]) {
00200   //  if(begin(id)!=end())
00201   //if(state && state->buttons[LFrPawOffset]) cout << "getAngles..." << flush;
00202   if(state==NULL) {
00203     // we haven't gotten the WorldState memory region from Main yet, just set LEDs to a wierd pattern and leave
00204     for(uint f=0;f<NumFrames;f++)
00205       for(uint i=0; i<NumOutputs; i++)
00206         outputs[f][i]=0;
00207     for(uint f=0;f<NumFrames;f++)
00208       for(uint l=0; l<NumLEDs; l++)
00209         outputs[f][l]=l/(NumLEDs-1.0);
00210     //  if(begin(id)!=end())
00211     //if(state && state->buttons[LFrPawOffset]) cout << "getangles-nostate-done..." << flush;
00212     return;
00213   }
00214   func_begin();
00215   //  if(begin(id)!=end())
00216   //  cout << id << "..." << flush;
00217   //  cout << "CHECKOUT..." << flush;
00218   for(uint output=0; output<NumOutputs; output++)
00219     cmdstates[output].clear();
00220 
00221   //  std::cout << "UPDATE..." << std::flush;
00222   std::list<MC_ID> unlocked;
00223   for(MC_ID it=begin(); it!=end(); it=next(it)) // check out all the MotionCommands (only one at a time tho)
00224     unlocked.push_back(it);
00225   while(unlocked.size()>0) { // keep cycling through all the locks we didn't get
00226     for(std::list<MC_ID>::iterator it=unlocked.begin(); it!=unlocked.end(); ) {
00227       MotionCommand* mc=checkoutMotion(*it,false);
00228       if(mc==NULL)
00229         it++; //we didn't get a lock, skip it (we'll keep looping until we get it)
00230       else {
00231         // we got a lock
00232         cur_cmd=*it;
00233         if(mc->shouldPrune()) {
00234           cout << "Removing expired" << endl;
00235           removeMotion(*it);
00236         } else
00237           mc->updateOutputs(); // the MotionCommand should make calls to setOutput from within here
00238         checkinMotion(*it); // release lock, done with motion
00239         // remove id from list of unprocessed motioncommands
00240         std::list<MC_ID>::iterator rem=it++;
00241         unlocked.erase(rem);
00242       }
00243     }
00244     cur_cmd=invalid_MC_ID;
00245   }
00246 
00247   // sort the list of requested outputs based on priority
00248   // (insertion sort, data structure is linked list)
00249   for(uint output=0; output<NumOutputs; output++) {
00250     cmdstatelist_t& curstatelist=cmdstates[output];
00251     for(cmdstatelist_t::index_t bit=curstatelist.begin(); bit!=curstatelist.end(); bit=curstatelist.next(bit)) {
00252       MC_ID high_ent=bit;
00253       float high_p=cmdlist[curstatelist[high_ent].mcid].priority;
00254       for(cmdstatelist_t::index_t cit=curstatelist.next(bit); cit!=curstatelist.end(); cit=curstatelist.next(cit)) {
00255         float curp=cmdlist[curstatelist[cit].mcid].priority;
00256         if(curp>high_p) {
00257           high_p=curp;
00258           high_ent=cit;
00259         }
00260       }
00261       curstatelist.swap(bit,high_ent);
00262       /*if(curstatelist.countf()!=curstatelist.countb() || curstatelist.countf()!=curstatelist.size()) {
00263         cout << "LOST ONE! " << bit << ' ' << high_ent << endl;
00264         cout << curstatelist.countf() << ' ' << curstatelist.countb() << ' ' << curstatelist.size() << endl;
00265         }*/
00266       bit=high_ent;
00267     }
00268   }
00269 
00270   // now we've got, for each output, a list of requested values sorted by priority
00271   // summarize each output
00272   for(uint frame=0; frame<NumFrames; frame++)
00273     for(uint output=0; output<NumOutputs; output++) {
00274       cmdstatelist_t& curstatelist=cmdstates[output];
00275       float alpha=1;
00276       OutputCmd sumcmd;
00277       cmdstatelist_t::index_t ent=curstatelist.begin();
00278       while(ent!=curstatelist.end() && alpha>0) {
00279         OutputCmd curcmd;
00280         float curp=curstatelist[ent].priority;
00281         float curalpha=1; // curalpha is multiplicative sum of leftovers (weights between 0 and 1)
00282         for(;curstatelist[ent].priority==curp; ent=curstatelist.next(ent)) {
00283           //weighted average within priority level
00284           float curweight=curstatelist[ent].frames[frame].weight;
00285           ASSERT(curweight>=0,"negative output weights are illegal");
00286           if(curweight<0) { //negative weights are illegal
00287             cout << "weight=" << curweight << endl;
00288             curweight=0;
00289           }
00290           curcmd.value+=curstatelist[ent].frames[frame].value*curweight;
00291           curcmd.weight+=curweight;
00292           if(curweight<1)
00293             curalpha*=(1-curweight);
00294           else
00295             curalpha=0;
00296         }
00297         if(curcmd.weight>0) {
00298           //weighted average of priority levels
00299           sumcmd.value+=curcmd.value/curcmd.weight*(1-curalpha);
00300           sumcmd.weight+=(1-curalpha);
00301           alpha*=curalpha;
00302         }
00303       }
00304       if(sumcmd.weight>0) 
00305         outputs[frame][output]=sumcmd.value/sumcmd.weight;
00306       else //if zero weight, hold last value
00307         outputs[frame][output]=cmdSums[output];
00308       if(frame==NumFrames-1)
00309         cmds[output]=sumcmd;
00310     }
00311   
00312   for(uint output=0; output<NumOutputs; output++)
00313     cmdSums[output]=outputs[NumFrames-1][output];
00314         
00315   // now summarize each output's PID values (for those which use PID control)
00316   for(uint output=PIDJointOffset; output<PIDJointOffset+NumPIDJoints; output++) {
00317     cmdstatelist_t& curstatelist=cmdstates[output];
00318     float alpha=1;
00319     float sumpid[3];
00320     for(uint i=0; i<3; i++)
00321       sumpid[i]=0;
00322     float sumweight=0;
00323     cmdstatelist_t::index_t ent=curstatelist.begin();
00324     while(ent!=curstatelist.end() && alpha>0) {
00325       float tmppid[3];
00326       for(uint i=0; i<3; i++)
00327         tmppid[i]=0;
00328       float tmpweight=0;
00329       float curp=curstatelist[ent].priority;
00330       float curalpha=1; // curalpha is multiplicative sum of leftovers (weights between 0 and 1)
00331       for(;curstatelist[ent].priority==curp; ent=curstatelist.next(ent)) {
00332         //weighted average within priority level
00333         float curweight=curstatelist[ent].pid.weight;
00334         ASSERT(curweight>=0,"negative PID weights are illegal")
00335         if(curweight<0) //negative weights are illegal
00336           curweight=0;
00337         for(uint i=0; i<3; i++)
00338           tmppid[i]+=curstatelist[ent].pid.pid[i]*curweight;
00339         tmpweight+=curweight;
00340         if(curweight<1)
00341           curalpha*=(1-curweight);
00342         else
00343           curalpha=0;
00344       }
00345       if(tmpweight>0) {
00346         //weighted average of priority levels
00347         for(uint i=0; i<3; i++)
00348           sumpid[i]+=tmppid[i]/tmpweight*(1-curalpha);
00349         sumweight+=(1-curalpha);
00350         alpha*=curalpha;
00351       }
00352     }
00353     if(sumweight>0) {
00354       for(uint i=0; i<3; i++)
00355         sumpid[i]/=sumweight;
00356       setPID(output,sumpid);
00357     }
00358   }
00359 
00360   func_end();
00361   //  if(begin(id)!=end())
00362   //if(state && state->buttons[LFrPawOffset]) cout << "getAngles-done." << flush;
00363 }
00364 
00365 void
00366 MotionManager::updateWorldState() {
00367   for(uint output=LEDOffset; output<LEDOffset+NumLEDs; output++)
00368     state->outputs[output]=cmdSums[output];
00369   for(uint output=BinJointOffset; output<BinJointOffset+NumBinJoints; output++)
00370     state->outputs[output]=cmdSums[output];
00371   if(state->robotDesign & WorldState::ERS210Mask) {
00372     for(uint output=0; output<NumPIDJoints; output++)      //NOTE: Should probably be NumOutputs for portability, but this is faster
00373       if(!ERS210Info::IsRealERS210[output])
00374         state->outputs[output]=cmdSums[output];
00375   } else if(state->robotDesign & WorldState::ERS220Mask) {
00376     for(uint output=0; output<NumPIDJoints; output++)      //NOTE: Should probably be NumOutputs for portability, but this is faster
00377       if(!ERS220Info::IsRealERS220[output])
00378         state->outputs[output]=cmdSums[output];
00379   } else
00380     cout << "MotionManager::updateWorldState() - could not detect model" << endl;
00381 }
00382 
00383 #ifdef PLATFORM_APERIOS
00384 
00385 bool
00386 MotionManager::updatePIDs(OPrimitiveID primIDs[NumOutputs]) {
00387   bool dirty=!pidchanges.empty();
00388   while(!pidchanges.empty()) {
00389     float gain[3];
00390     word shift[3];
00391     for(uint i=0; i<3; i++) {
00392       gain[i]=pidchanges.front().pids[i]*2;
00393       shift[i]=0xF;
00394       while(shift[i]!=0 && gain[i]!=(int)gain[i] && gain[i]<(1<<15)) {
00395         gain[i]*=2;
00396         shift[i]--;
00397       }
00398     }
00399     OPENR::SetJointGain(primIDs[pidchanges.front().joint],(word)gain[0],(word)gain[1],(word)gain[2],shift[0],shift[1],shift[2]);
00400     for(uint i=0; i<3; i++)
00401       state->pids[pidchanges.front().joint][i]=pidchanges.front().pids[i];
00402     pidchanges.pop_front();
00403   }
00404   return dirty;
00405 }
00406 
00407 // documentation for this function is at the end of the file
00408 MotionManager::MC_ID
00409 MotionManager::addMotion(const SharedObjectBase& sm) {
00410   //  cout << "addMotion..." << flush;
00411   while(numAcc<MAX_ACCESS-1) { std::cout << "WAIT" << std::flush; } //Wait for everyone to register
00412   func_begin();
00413   //  cout << id << "..." << flush;
00414   MotionCommand * mc = dynamic_cast<MotionCommand*>(reinterpret_cast<MotionManagerMsg*>(sm.data()));
00415   if(mc==NULL) {
00416     cout << "MotionManager::addMotion() - SharedObject does not seem to hold a MotionCommand" << endl;
00417     return invalid_MC_ID;
00418   }
00419   MC_ID mc_id = pop_free();
00420   if(mc_id==cmdlist.end()) {
00421     cout << "MotionManager::addMotion() - Out of room, could not add" << endl;
00422     return func_end(cmdlist.end());
00423   }
00424   cmdlist[mc_id].baseaddrs[_MMaccID]=mc;
00425   cmdlist[mc_id].rcr[_MMaccID]=sm.getRegion();
00426   //cout << "addMotion(): sm.getRegion()->NumberOfReference()==" << sm.getRegion()->NumberOfReference() << endl;
00427   cmdlist[mc_id].rcr[_MMaccID]->AddReference();
00428   //cout << "addMotion()NOW: sm.getRegion()->NumberOfReference()==" << sm.getRegion()->NumberOfReference() << endl;
00429   cmdlist[mc_id].lastAccessor=_MMaccID;
00430   cmdlist[mc_id].priority=kStdPriority;
00431   mc->setAdd(mc_id);
00432   OStatus err;
00433   ASSERT((err=subjs[_MMaccID]->SetData(sm.getRegion()))==oSUCCESS,"*** ERROR MotionManager: SetData returned " << err);
00434   //cout << "addMotion()afterSetData: sm.getRegion()->NumberOfReference()==" << sm.getRegion()->NumberOfReference() << endl;
00435   ASSERT((err=subjs[_MMaccID]->NotifyObservers())==oSUCCESS,"*** ERROR MotionManager: NotifyObservers returned " << err);
00436   //  cout << "addMotion-done" << endl;
00437   return func_end(mc_id);
00438 }
00439 MotionManager::MC_ID 
00440 MotionManager::addMotion(const SharedObjectBase& sm, float priority) {
00441   func_begin();
00442   MC_ID mcid=addMotion(sm);
00443   if(mcid!=end())
00444     setPriority(mcid,priority);
00445   return func_end(mcid);
00446 }
00447 MotionManager::MC_ID 
00448 MotionManager::addMotion(const SharedObjectBase& sm, bool autoprune) {
00449   MotionCommand * mc = dynamic_cast<MotionCommand*>(reinterpret_cast<MotionManagerMsg*>(sm.data()));
00450   if(mc==NULL) {
00451     cout << "MotionManager::addMotion() - SharedObject does not seem to hold a MotionCommand" << endl;
00452     return invalid_MC_ID;
00453   }
00454   mc->setAutoPrune(autoprune);
00455   return addMotion(sm); 
00456 }
00457 MotionManager::MC_ID 
00458 MotionManager::addMotion(const SharedObjectBase& sm, float priority, bool autoprune) {
00459   func_begin();
00460   MotionCommand * mc = dynamic_cast<MotionCommand*>(reinterpret_cast<MotionManagerMsg*>(sm.data()));
00461   if(mc==NULL) {
00462     cout << "MotionManager::addMotion() - SharedObject does not seem to hold a MotionCommand" << endl;
00463     return invalid_MC_ID;
00464   }
00465   mc->setAutoPrune(autoprune);
00466   MC_ID mcid=addMotion(sm);
00467   if(mcid!=end())
00468     setPriority(mcid,priority);
00469   return func_end(mcid);
00470 }
00471 
00472 void
00473 MotionManager::receivedMsg(const ONotifyEvent& event) {
00474   //  cout << "receivedMsg..." << flush;
00475   func_begin();
00476   //  cout << id << "..." << flush;
00477   for(int x=0; x<event.NumOfData(); x++) {
00478     RCRegion * rcr = event.RCData(x);
00479     MotionManagerMsg * mminfo = reinterpret_cast<MotionManagerMsg*>(rcr->Base());
00480     MC_ID mc_id=mminfo->mc_id;
00481     switch(mminfo->type) {
00482     case MotionManagerMsg::addMotion: {
00483       //cout << "receiveMotion(): rcr->NumberOfReference()==" << rcr->NumberOfReference() << endl;
00484       rcr->AddReference();
00485       //cout << "receiveMotion()NOW: rcr->NumberOfReference()==" << rcr->NumberOfReference() << endl;
00486       cmdlist[mc_id].rcr[_MMaccID]=rcr;
00487       //should be able to do a nice dynamic cast instead of a static one
00488       // but it gives NULL for some reason - i blame having to do the fork trick
00489       cmdlist[mc_id].baseaddrs[_MMaccID]=static_cast<MotionCommand*>(mminfo);
00490       erouter->postEvent(new EventBase(EventBase::motmanEGID,mc_id,EventBase::activateETID,00));
00491       cmdlist[mc_id].baseaddrs[_MMaccID]->DoStart();
00492     } break;
00493     case MotionManagerMsg::deleteMotion: {
00494       //cout << "deleteMotion(): cmdlist[mc_id].rcr[_MMaccID]->NumberOfReference()==" << cmdlist[mc_id].rcr[_MMaccID]->NumberOfReference() << endl;
00495       cmdlist[mc_id].rcr[_MMaccID]->RemoveReference();
00496       //cout << "deleteMotion()NOW: cmdlist[mc_id].rcr[_MMaccID]->NumberOfReference()==" << cmdlist[mc_id].rcr[_MMaccID]->NumberOfReference() << endl;
00497     } break;
00498     default:
00499       printf("*** WARNING *** unknown MotionManager msg type received\n");
00500     }
00501   }
00502   //  cout << "receivedMsg-done" << endl;
00503   func_end();
00504 }
00505 
00506 #endif //PLATFORM_APERIOS
00507 
00508 MotionCommand *
00509 MotionManager::checkoutMotion(MC_ID mcid,bool block) {
00510   //cout << "checkout..." << flush;
00511   if(mcid>=MAX_MOTIONS) {
00512     cout << "*** WARNING *** " << _MMaccID << " tried to access invalid mcid " << mcid << endl;
00513     return NULL;
00514   }
00515   if(block)
00516     cmdlist[mcid].lock.lock(_MMaccID);
00517   else
00518     if(!cmdlist[mcid].lock.try_lock(_MMaccID))
00519       return NULL;
00520   if(cmdlist[mcid].lastAccessor==(accID_t)-1) {
00521     cout << "*** WARNING *** " << _MMaccID << " tried to access dead mcid " << mcid << endl;
00522     cmdlist[mcid].lock.release();
00523     return NULL;
00524   }
00525   //cout << "locked..." << endl;
00526   MotionCommand * base = cmdlist[mcid].baseaddrs[_MMaccID];
00527   //  cout << "base=" << base << "..." << flush;
00528   if(cmdlist[mcid].lastAccessor!=_MMaccID) {
00529     //cout << "converting from " << MCRegistrar::getRaw(base) << "..." << flush;
00530     //cout << "prev=" << accRegs[cmdlist[mcid].lastAccessor].getReg(base) << "..." << flush;
00531     //    accRegs[id].convert(base);
00532     //cout << "to=" << MCRegistrar::getRaw(base) << ", " << accRegs[cmdlist[mcid].lastAccessor].getReg(base) << endl;
00533     cmdlist[mcid].lastAccessor=_MMaccID;
00534   }
00535   //cout << "checkout-done..." << flush;
00536   return base;
00537 }
00538 
00539 void
00540 MotionManager::checkinMotion(MC_ID mcid) {
00541   if(mcid!=invalid_MC_ID)
00542     cmdlist[mcid].lock.release();
00543 }
00544 
00545 void
00546 MotionManager::removeMotion(MC_ID mcid) {
00547   if(mcid==invalid_MC_ID)
00548     return;
00549   func_begin();
00550   checkoutMotion(mcid,true);
00551   cmdlist[mcid].baseaddrs[_MMaccID]->DoStop();
00552   erouter->postEvent(new EventBase(EventBase::motmanEGID,mcid,EventBase::deactivateETID,00));
00553 #ifdef PLATFORM_APERIOS
00554   MotionManagerMsg dmsg;
00555   dmsg.setDelete(mcid);
00556   subjs[_MMaccID]->SetData(&dmsg,sizeof(dmsg));
00557   subjs[_MMaccID]->NotifyObservers();
00558   //cout << "removeMotion(): cmdlist[mcid].rcr[_MMaccID]->NumberOfReference()==" << cmdlist[mcid].rcr[_MMaccID]->NumberOfReference() << endl;
00559   cmdlist[mcid].rcr[_MMaccID]->RemoveReference();
00560   //cout << "removeMotion()NOW: cmdlist[mcid].rcr[_MMaccID]->NumberOfReference()==" << cmdlist[mcid].rcr[_MMaccID]->NumberOfReference() << endl;
00561 #endif //PLATFORM_APERIOS
00562   push_free(mcid);
00563   checkinMotion(mcid);
00564   func_end();
00565 }
00566 
00567 
00568 /*! Note that we don't actually set the PIDs in the system here, we just queue them up.
00569  *  PID changes seem to be an expensive operation, so may only want to clear the queue
00570  *  at some reduced rate (although that's not actually currently implemented, so right
00571  *  now there's no real benefit until that's done) */
00572 void
00573 MotionManager::setPID(unsigned int joint, const float pids[3]) {
00574   func_begin();
00575   //see if there's already an update for this joint
00576   for(uint u = pidchanges.begin(); u!=pidchanges.end(); u=pidchanges.next(u)) {
00577     if(pidchanges[u].joint==joint) { //found it
00578       for(uint i=0; i<3; i++) {
00579         pidchanges[i].pids[i]=pids[i];
00580         if(pids[i]!=state->pids[joint][i]) { //see if we're setting back to current PID
00581           for(i++; i<3; i++) //we aren't, copy over the rest
00582             pidchanges[i].pids[i]=pids[i];
00583           func_end();
00584           return;
00585         }
00586       }
00587       //if it didn't return within the loop, no difference was found from current state
00588       //so just delete the update
00589       pidchanges.erase(u);
00590       func_end();
00591       return;
00592     }
00593   }
00594   //if we didn't return from the loop, we didn't find an update for the joint
00595   for(uint i=0; i<3; i++) //check to see if it's different from the current
00596     if(pids[i]!=state->pids[joint][i]) {
00597       PIDUpdate update(joint,pids); //it is different, insert a new update
00598       pidchanges.push_back(update);
00599       break;
00600     }
00601   func_end();
00602 }
00603 
00604 
00605 MotionManager::MC_ID
00606 MotionManager::skip_ahead(MC_ID mcid) const {
00607   // this is in case a new motion has been added, but the current
00608   // process hasn't received its own copy yet, so should skip over them
00609 #ifdef PLATFORM_APERIOS
00610   while(mcid!=cmdlist.end() && cmdlist[mcid].rcr[_MMaccID]==NULL)
00611     mcid=cmdlist.next(mcid);
00612   return mcid;
00613 #else
00614   return cmdlist.next(mcid);
00615 #endif
00616 }
00617 
00618 MotionManager::OutputState::OutputState()
00619   : priority(0),mcid(MotionManager::invalid_MC_ID), pid()
00620 {}
00621 MotionManager::OutputState::OutputState(unsigned int out, float pri, MC_ID mc, const OutputCmd cmds[NumFrames])
00622   : priority(pri),mcid(mc), pid(DefaultPIDs[out])
00623 {
00624   for(unsigned int i=0; i<NumFrames; i++)
00625     frames[i]=cmds[i];
00626 }
00627 MotionManager::OutputState::OutputState(unsigned int out, float pri, MC_ID mc, const OutputCmd& cmd)
00628   : priority(pri),mcid(mc), pid(DefaultPIDs[out])
00629 {
00630   for(unsigned int i=0; i<NumFrames; i++)
00631     frames[i]=cmd;
00632 }
00633 MotionManager::OutputState::OutputState(unsigned int out, float pri, MC_ID mc, const OutputCmd& cmd, unsigned int frame)
00634   : priority(pri),mcid(mc), pid(DefaultPIDs[out])
00635 {
00636   frames[frame]=cmd;
00637 }
00638 MotionManager::OutputState::OutputState(unsigned int /*out*/, float pri, MC_ID mc, const OutputPID& p)
00639   : priority(pri),mcid(mc), pid(p)
00640 {}
00641 MotionManager::OutputState::OutputState(unsigned int /*out*/, float pri, MC_ID mc, const OutputCmd cmds[NumFrames], const OutputPID& p)
00642   : priority(pri),mcid(mc), pid(p)
00643 {
00644   for(unsigned int i=0; i<NumFrames; i++)
00645     frames[i]=cmds[i];
00646 }
00647 MotionManager::OutputState::OutputState(unsigned int /*out*/, float pri, MC_ID mc, const OutputCmd& cmd, const OutputPID& p)
00648   : priority(pri),mcid(mc), pid(p)
00649 {
00650   for(unsigned int i=0; i<NumFrames; i++)
00651     frames[i]=cmd;
00652 }
00653 
00654 
00655 /*! @file
00656  * @brief Implements MotionManager, simplifies sharing of MotionCommand's and provides mutual exclusion to their access
00657  * @author ejt (Creator)
00658  *
00659  * $Author: ejt $
00660  * $Name: tekkotsu-1_5 $
00661  * $Revision: 1.25 $
00662  * $State: Rel $
00663  * $Date: 2003/10/07 01:00:40 $
00664  */
00665 
00666 
00667 /*
00668     for(uint f=0;f<NumFrames;f++)
00669       for(uint i=0; i<NumOutputs; i++)
00670         outputs[f][i]=0;
00671     const uint cyctime=128;
00672     uint ot=get_time()+3*cyctime;
00673     for(uint f=0;f<NumFrames;f++) {
00674       uint t=ot+f*FrameTime;
00675       outputs[f][TopBrLEDOffset]=(t/(double)cyctime-t/cyctime)*.75+.25;
00676       t-=cyctime;
00677       outputs[f][TopLLEDOffset]=(t/(double)cyctime-t/cyctime)*.75+.25;
00678       outputs[f][TopRLEDOffset]=(t/(double)cyctime-t/cyctime)*.75+.25;
00679       t-=cyctime;
00680       outputs[f][MidLLEDOffset]=(t/(double)cyctime-t/cyctime)*.75+.25;
00681       outputs[f][MidRLEDOffset]=(t/(double)cyctime-t/cyctime)*.75+.25;
00682       t-=cyctime;
00683       outputs[f][BotLLEDOffset]=(t/(double)cyctime-t/cyctime)*.75+.25;
00684       outputs[f][BotRLEDOffset]=(t/(double)cyctime-t/cyctime)*.75+.25;
00685     }
00686 */
00687 
00688   /*  for(uint output=TlRedLEDOffset-1; output<LEDOffset+NumLEDs-1; output++) {
00689     cmdstatelist_t& curstatelist=cmdstates[output];
00690     cout << "Out " << output << ": ";
00691     for(cmdstatelist_t::index_t bit=curstatelist.begin(); bit!=curstatelist.end(); bit=curstatelist.next(bit))
00692       cout << '('<<curstatelist[bit].mcid<<','<<cmdlist[curstatelist[bit].mcid].priority<<','<<curstatelist[bit].frames[0].value<<','<<curstatelist[bit].frames[0].weight<<") ";
00693     cout << endl;
00694     }*/
00695 
00696 
00697   /*  cout << get_time() << ' ' << size() << endl;
00698   for(uint output=TlRedLEDOffset; output<LEDOffset+NumLEDs-1; output++) {
00699     cmdstatelist_t& curstatelist=cmdstates[output];
00700     cout << "Out " << output << ": ";
00701     for(cmdstatelist_t::index_t bit=curstatelist.begin(); bit!=curstatelist.end(); bit=curstatelist.next(bit))
00702       cout << '('<<curstatelist[bit].mcid<<','<<cmdlist[curstatelist[bit].mcid].priority<<','<<curstatelist[bit].frames[0].value<<','<<curstatelist[bit].frames[0].weight<<") ";
00703     cout << endl;
00704   }
00705   */

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