Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
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 #include "Shared/StackTrace.h"
00006 #include "Shared/ProjectInterface.h"
00007 
00008 #ifndef PLATFORM_APERIOS
00009 #  include "IPC/MessageQueue.h"
00010 #  include "IPC/MessageReceiver.h"
00011 #  include "Shared/ProjectInterface.h"
00012 #endif
00013 
00014 #include "Shared/ERS210Info.h"
00015 #include "Shared/ERS220Info.h"
00016 #include "Shared/ERS7Info.h"
00017 
00018 #include <list>
00019 
00020 MotionManager * motman=NULL;
00021 int MotionManager::_MMaccID=-1U;
00022 EventTranslator* MotionManager::etrans=NULL;
00023 
00024 const float MotionManager::kIgnoredPriority    =-1;
00025 const float MotionManager::kBackgroundPriority = 0;
00026 const float MotionManager::kLowPriority        = 5;
00027 const float MotionManager::kStdPriority        = 10;
00028 const float MotionManager::kHighPriority       = 50;
00029 const float MotionManager::kEmergencyPriority  = 100;
00030 
00031 using namespace std;
00032 
00033 //! just for convenience
00034 typedef unsigned int uint;
00035 
00036 MotionManager::MotionManager()
00037 : pidchanges(),cmdlist(),cur_cmd(invalid_MC_ID),MMlock(),numAcc(0)
00038 {
00039   for(uint x=0; x<NumOutputs; x++)
00040     cmdSums[x]=0;
00041 }
00042 
00043 #ifdef PLATFORM_APERIOS
00044 
00045 void
00046 MotionManager::InitAccess(OSubject* subj) {
00047   if(numAcc==MAX_ACCESS) {
00048     printf("*** ERROR *** attempted to register more accessors with MotionManager than allowed by MAX_ACCESS\n");
00049     return;
00050   }
00051   _MMaccID=numAcc++;
00052   //  cout << "ID is now " << _MMaccID << " of " << numAcc << endl;
00053   //  cout << "_MMaccID is " << &_MMaccID << endl;
00054   //  cout << "numAcc is " << &numAcc << " from " << this << endl;
00055   MMlock.lock(_MMaccID);
00056   //  accRegs[accID].init();
00057   subjs[_MMaccID]=subj;
00058   if(cmdlist.size()>0) //Shouldn't happen - busy wait in addMotion
00059     cout << "*** WARNING *** MOTIONS ADDED BEFORE ALL INITACCESSED" << endl;
00060   MMlock.unlock();
00061 }
00062 
00063 #else //now PLATFORM_LOCAL
00064 
00065 void
00066 MotionManager::InitAccess(MessageQueueBase& mcbufq, Resource& behaviorLock) {
00067   if(numAcc==MAX_ACCESS) {
00068     printf("*** ERROR *** attempted to register more accessors with MotionManager than allowed by MAX_ACCESS\n");
00069     return;
00070   }
00071   _MMaccID=numAcc++;
00072   //  cout << "ID is now " << _MMaccID << " of " << numAcc << endl;
00073   //  cout << "_MMaccID is " << &_MMaccID << endl;
00074   //  cout << "numAcc is " << &numAcc << " from " << this << endl;
00075   MMlock.lock(_MMaccID);
00076   subjs[_MMaccID]=&mcbufq;
00077   mcrecvs[_MMaccID]=new MessageReceiver(*subjs[_MMaccID],receivedMsg);
00078   procLocks[_MMaccID]=&behaviorLock;
00079   if(cmdlist.size()>0) //Shouldn't happen - busy wait in doAddMotion
00080     cout << "*** WARNING *** MOTIONS ADDED BEFORE ALL INITACCESSED" << endl;
00081   MMlock.unlock();
00082 }
00083 
00084 #endif //PLATFORM-specific initialization
00085 
00086 void
00087 MotionManager::RemoveAccess() {
00088 #ifndef PLATFORM_APERIOS
00089   //kill the message receiver before we get the motion manager lock
00090   // that way if there's a message pending, it can be processed instead of deadlocking
00091   mcrecvs[_MMaccID]->finish();
00092   delete mcrecvs[_MMaccID];
00093   mcrecvs[_MMaccID]=NULL;
00094 #endif
00095   
00096   func_begin();
00097   for(MC_ID mc_id=cmdlist.begin(); mc_id!=cmdlist.end(); mc_id=cmdlist.next(mc_id)) {
00098     if(cmdlist[mc_id].rcr[_MMaccID]!=NULL) {
00099       MotionCommand* mc=checkoutMotion(mc_id,true);
00100       int found=0;
00101       for(unsigned int i=0; i<numAcc; i++) {
00102         if(cmdlist[mc_id].rcr[i]!=NULL) {
00103           found++;
00104         }
00105       }
00106       cout << "Warning: " << ProcessID::getIDStr() << " dropping motion command " << mc_id << ", was active at shutdown " << (mc->getAutoPrune()?"(was set for autoprune)":"(leaked?)") << endl;
00107 #ifdef PLATFORM_APERIOS
00108       int refs=1;
00109 #else
00110       int refs=cmdlist[mc_id].rcr[_MMaccID]->NumberOfLocalReference();
00111 #endif
00112       if(refs>1)
00113         cout << "Warning: " << ProcessID::getIDStr() << " still had " <<  refs-1 << " references to motion command " << mc_id << " as it was being dropped (these are now invalid)" << endl;
00114       for(int i=0; i<refs; ++i)
00115         cmdlist[mc_id].rcr[_MMaccID]->RemoveReference();
00116       cmdlist[mc_id].rcr[_MMaccID]=NULL;
00117       if(found==1) {
00118         MC_ID p=cmdlist.prev(mc_id);
00119         push_free(mc_id); //don't check in -- lock destructor will release the lock as the entry is destructed
00120         mc_id=p;
00121       } else {
00122         checkinMotion(mc_id);
00123       }
00124     }
00125   }
00126   func_end();
00127 }
00128 
00129 
00130 MotionManager::~MotionManager() {
00131   if(!cmdlist.empty()) {
00132     func_begin();
00133     cout << "WARNING: MotionManager destruction with MotionCommands still attached." << endl;
00134     while(!cmdlist.empty()) {
00135       MC_ID mc_id=cmdlist.begin();
00136       for(unsigned int i=0; i<numAcc; i++)
00137         if(cmdlist[mc_id].rcr[i]!=NULL)
00138           cout << "MC " << mc_id << " was still referenced by InitAccess caller #" << _MMaccID << endl;
00139       push_free(mc_id);
00140     }
00141     func_end();
00142   }
00143 }
00144 
00145 void
00146 MotionManager::setOutput(const MotionCommand* caller, unsigned int output, const OutputCmd& cmd) {
00147   if(output >= NumOutputs)
00148     return;
00149   if(cmd.weight<=0)
00150     return;
00151 
00152   if(caller==NULL || caller->getID()!=cur_cmd)
00153     func_begin();
00154   if(cur_cmd==invalid_MC_ID) {
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));
00161     else
00162       for(unsigned int i=0; i<NumFrames; i++)
00163         curstatelist[ent].frames[i]=cmd;
00164   }
00165   if(caller==NULL || caller->getID()!=cur_cmd)
00166     func_end();
00167 }
00168 
00169 void
00170 MotionManager::setOutput(const MotionCommand* caller, unsigned int output, const OutputCmd& cmd, unsigned int frame) {
00171   if(output >= NumOutputs)
00172     return;
00173   if(cmd.weight<=0)
00174     return;
00175 
00176   if(caller==NULL || caller->getID()!=cur_cmd)
00177     func_begin();
00178   if(cur_cmd==invalid_MC_ID) {
00179     cmdSums[output]=cmd.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,cmd,frame));
00185     else
00186       curstatelist[ent].frames[frame]=cmd;
00187   }
00188   if(caller==NULL || caller->getID()!=cur_cmd)
00189     func_end();
00190 }
00191 
00192 void 
00193 MotionManager::setOutput(const MotionCommand* caller, unsigned int output, const OutputCmd ocmds[NumFrames]) {
00194   if(output >= NumOutputs)
00195     return;
00196   unsigned int hasWeight=NumFrames;
00197   for(unsigned int i=NumFrames-1; i!=0; i--)
00198     if(ocmds[i].weight>0) {
00199       hasWeight=i;
00200       break;
00201     }
00202   if(hasWeight==NumFrames)
00203     return;
00204   
00205 
00206   if(caller==NULL || caller->getID()!=cur_cmd)
00207     func_begin();
00208   if(cur_cmd==invalid_MC_ID) {
00209     cmdSums[output]=ocmds[hasWeight].value;
00210   } else if(getPriority(cur_cmd)>=kBackgroundPriority) {
00211     cmdstatelist_t& curstatelist=cmdstates[output];
00212     cmdstatelist_t::index_t ent=curstatelist.begin();
00213     if(ent==curstatelist.end() || curstatelist[ent].mcid!=cur_cmd)
00214       curstatelist.push_front(OutputState(output,getPriority(cur_cmd),cur_cmd,ocmds));
00215     else
00216       for(unsigned int i=0; i<NumFrames; i++)
00217         curstatelist[ent].frames[i]=ocmds[i];
00218   }
00219   if(caller==NULL || caller->getID()!=cur_cmd)
00220     func_end();
00221 }
00222 
00223 void
00224 MotionManager::setOutput(const MotionCommand* caller, unsigned int output, const OutputPID& pid) {
00225   if(output >= NumOutputs)
00226     return;
00227 
00228   if(caller==NULL || caller->getID()!=cur_cmd)
00229     func_begin();
00230   if(cur_cmd==invalid_MC_ID) {
00231     setPID(output,pid.pid);
00232   } else if(getPriority(cur_cmd)>=kBackgroundPriority) {
00233     cmdstatelist_t& curstatelist=cmdstates[output];
00234     cmdstatelist_t::index_t ent=curstatelist.begin();
00235     if(ent==curstatelist.end() || curstatelist[ent].mcid!=cur_cmd)
00236       curstatelist.push_front(OutputState(output,getPriority(cur_cmd),cur_cmd,pid));
00237     else
00238       curstatelist[ent].pid=pid;
00239   }
00240   if(caller==NULL || caller->getID()!=cur_cmd)
00241     func_end();
00242 }
00243 
00244 void
00245 MotionManager::setOutput(const MotionCommand* caller, unsigned int output, const OutputCmd& cmd, const OutputPID& pid) {
00246   if(output >= NumOutputs)
00247     return;
00248 
00249   if(caller==NULL || caller->getID()!=cur_cmd)
00250     func_begin();
00251   if(cur_cmd==invalid_MC_ID) {
00252     if(cmd.weight>0)
00253       cmdSums[output]=cmd.value;
00254     setPID(output,pid.pid);
00255   } else if(getPriority(cur_cmd)>=kBackgroundPriority) {
00256     cmdstatelist_t& curstatelist=cmdstates[output];
00257     cmdstatelist_t::index_t ent=curstatelist.begin();
00258     if(ent==curstatelist.end() || curstatelist[ent].mcid!=cur_cmd)
00259       curstatelist.push_front(OutputState(output,getPriority(cur_cmd),cur_cmd,cmd,pid));
00260     else {
00261       for(unsigned int i=0; i<NumFrames; i++)
00262         curstatelist[ent].frames[i]=cmd;
00263       curstatelist[ent].pid=pid;
00264     }
00265   }
00266   if(caller==NULL || caller->getID()!=cur_cmd)
00267     func_end();
00268 }
00269 
00270 void
00271 MotionManager::setOutput(const MotionCommand* caller, unsigned int output, const OutputCmd ocmds[NumFrames], const OutputPID& pid) {
00272   if(output >= NumOutputs)
00273     return;
00274 
00275   if(caller==NULL || caller->getID()!=cur_cmd)
00276     func_begin();
00277   if(cur_cmd==invalid_MC_ID) {
00278     if(ocmds[NumFrames-1].weight>0)
00279       cmdSums[output]=ocmds[NumFrames-1].value;
00280     setPID(output,pid.pid);
00281   } else if(getPriority(cur_cmd)>=kBackgroundPriority) {
00282     cmdstatelist_t& curstatelist=cmdstates[output];
00283     cmdstatelist_t::index_t ent=curstatelist.begin();
00284     if(ent==curstatelist.end() || curstatelist[ent].mcid!=cur_cmd)
00285       curstatelist.push_front(OutputState(output,getPriority(cur_cmd),cur_cmd,ocmds,pid));
00286     else {
00287       for(unsigned int i=0; i<NumFrames; i++)
00288         curstatelist[ent].frames[i]=ocmds[i];
00289       curstatelist[ent].pid=pid;
00290     }
00291   }
00292   if(caller==NULL || caller->getID()!=cur_cmd)
00293     func_end();
00294 }
00295 
00296 /*! What's worse? A plethora of functions which are only called, and only useful at one place,
00297  *  or a big massive function which doesn't pollute the namespace?  This is the latter, for
00298  *  better or worse. */
00299 void
00300 MotionManager::getOutputs(float outputs[][NumOutputs]) {
00301   //  if(begin(id)!=end())
00302   //if(state && state->buttons[LFrPawOffset]) cout << "getAngles..." << flush;
00303   if(state==NULL) {
00304     // we haven't gotten the WorldState memory region from Main yet, just set LEDs to a wierd pattern and leave
00305     for(uint f=0;f<NumFrames;f++)
00306       for(uint i=0; i<NumOutputs; i++)
00307         outputs[f][i]=0;
00308     for(uint f=0;f<NumFrames;f++)
00309       for(uint l=0; l<NumLEDs; l++)
00310         outputs[f][l]=l/(NumLEDs-1.0);
00311     //  if(begin(id)!=end())
00312     //if(state && state->buttons[LFrPawOffset]) cout << "getangles-nostate-done..." << flush;
00313     return;
00314   }
00315   func_begin();
00316   //  if(begin(id)!=end())
00317   //  cout << id << "..." << flush;
00318   //cout << "CHECKOUT..." << flush;
00319   for(uint output=0; output<NumOutputs; output++)
00320     cmdstates[output].clear();
00321 
00322   // for each PID joint which is set to 0 power, set the background
00323   // position value to current sensed value this prevents jerking back
00324   // to the previous position when joint(s) are moved during 0 power,
00325   // and then power is turned back on. (power here is in the 0 pid
00326   // sense, the joints are still receiving power from the system -
00327   // that's a separate system call)
00328   // Note that we wouldn't want to do this all the time, because
00329   // miscalibration between the sensed position and target position
00330   // will cause joints to drift to the extremities of motion, in some
00331   // cases, very quickly, and in worse cases, colliding with other
00332   // joints
00333   for(uint output=0; output<NumPIDJoints; output++)
00334     if(state->pids[output][0]==0 && state->pids[output][1]==0 && state->pids[output][2]==0)
00335       cmdSums[output]=state->outputs[output];
00336 
00337   //std::cout << "UPDATE..." << std::flush;
00338   std::list<MC_ID> unlocked;
00339   for(MC_ID it=begin(); it!=end(); it=next(it)) // check out all the MotionCommands (only one at a time tho)
00340     if(cmdlist[it].lastAccessor!=(accID_t)-1)
00341       unlocked.push_back(it);
00342   unsigned int lastProcessed=get_time();
00343   while(unlocked.size()>0) { // keep cycling through all the locks we didn't get
00344     for(std::list<MC_ID>::iterator it=unlocked.begin(); it!=unlocked.end(); ) {
00345       MotionCommand* mc=checkoutMotion(*it,false);
00346       if(mc==NULL)
00347         it++; //we didn't get a lock, skip it (we'll keep looping until we get it)
00348       else {
00349         // we got a lock
00350         cur_cmd=*it;
00351         bool prune=true;
00352         try {
00353           prune=mc->shouldPrune();
00354         } catch(const std::exception& ex) {
00355           ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionCommand prune test, will prune",&ex);
00356         } catch(...) {
00357           ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionCommand prune test, will prune",NULL);
00358         }
00359         if(prune) {
00360           cout << "Removing expired " << *it << " (autoprune)" << endl;
00361           checkinMotion(*it); // release lock, done with motion (don't need to (and shouldn't) keep lock through the removeMotion())
00362           //only the last process to receive the remove notification actually does the remove, and
00363           //wouldn't be able to undo the thread portion of the lock made in this process
00364           //so we have to take off our own lock here first.
00365           removeMotion(*it);
00366         } else {
00367           try {
00368             mc->updateOutputs(); // the MotionCommand should make calls to setOutput from within here
00369           } catch(const std::exception& ex) {
00370             ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionCommand updateOutputs",&ex);
00371           } catch(...) {
00372             ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionCommand updateOutputs",NULL);
00373           }
00374           checkinMotion(*it); // release lock, done with motion
00375         }
00376         cur_cmd=invalid_MC_ID;
00377         // remove id from list of unprocessed motioncommands
00378         std::list<MC_ID>::iterator rem=it++;
00379         unlocked.erase(rem);
00380         lastProcessed=get_time();
00381       }
00382     }
00383     if(get_time()-lastProcessed>FrameTime*NumFrames/2)
00384       break;
00385   }
00386   if(unlocked.size()>0) {
00387     cerr << "Warning: MotionManager was unable to obtain a lock on MCs: ";
00388     for(std::list<MC_ID>::iterator it=unlocked.begin(); it!=unlocked.end(); it++)
00389       cerr << *it << ' ';
00390     cerr << endl;
00391     cerr << (unlocked.size()>1?"They":"It") << " may have been left locked by a Behavior while it was busy." << endl;
00392     cerr << "Try reducing the scope of your MMAccessor or call checkinMotion sooner." << endl;
00393   }
00394 
00395   // sort the list of requested outputs based on priority
00396   // (insertion sort, data structure is linked list)
00397   for(uint output=0; output<NumOutputs; output++) {
00398     cmdstatelist_t& curstatelist=cmdstates[output];
00399     for(cmdstatelist_t::index_t bit=curstatelist.begin(); bit!=curstatelist.end(); bit=curstatelist.next(bit)) {
00400       MC_ID high_ent=bit;
00401       float high_p=cmdlist[curstatelist[high_ent].mcid].priority;
00402       for(cmdstatelist_t::index_t cit=curstatelist.next(bit); cit!=curstatelist.end(); cit=curstatelist.next(cit)) {
00403         float curp=cmdlist[curstatelist[cit].mcid].priority;
00404         if(curp>high_p) {
00405           high_p=curp;
00406           high_ent=cit;
00407         }
00408       }
00409       curstatelist.swap(bit,high_ent);
00410       /*if(curstatelist.countf()!=curstatelist.countb() || curstatelist.countf()!=curstatelist.size()) {
00411         cout << "LOST ONE! " << bit << ' ' << high_ent << endl;
00412         cout << curstatelist.countf() << ' ' << curstatelist.countb() << ' ' << curstatelist.size() << endl;
00413         }*/
00414       bit=high_ent;
00415     }
00416   }
00417 
00418   // now we've got, for each output, a list of requested values sorted by priority
00419   // summarize each output
00420   for(uint frame=0; frame<NumFrames; frame++)
00421     for(uint output=0; output<NumOutputs; output++) {
00422       cmdstatelist_t& curstatelist=cmdstates[output];
00423       float alpha=1;
00424       OutputCmd sumcmd;
00425       cmdstatelist_t::index_t ent=curstatelist.begin();
00426       while(ent!=curstatelist.end() && alpha>0) {
00427         OutputCmd curcmd;
00428         float curp=curstatelist[ent].priority;
00429         float curalpha=1; // curalpha is cumulative product of leftovers (weights between 0 and 1)
00430         for(;ent!=curstatelist.end() && curstatelist[ent].priority==curp; ent=curstatelist.next(ent)) {
00431           //weighted average within priority level
00432           float curweight=curstatelist[ent].frames[frame].weight;
00433           ASSERT(curweight>=0,"negative output weights are illegal, MC_ID="<<curstatelist[ent].mcid<<" joint="<<outputNames[output]<<" frame="<<frame<<" weight="<<curweight);
00434           if(curweight<0) //negative weights are illegal
00435             curweight=0;
00436           curcmd.value+=curstatelist[ent].frames[frame].value*curweight;
00437           curcmd.weight+=curweight;
00438           if(curweight<1)
00439             curalpha*=(1-curweight);
00440           else
00441             curalpha=0;
00442         }
00443         if(curcmd.weight>0) {
00444           //weighted average of priority levels
00445           sumcmd.value+=curcmd.value/curcmd.weight*alpha*(1-curalpha);
00446           sumcmd.weight+=alpha*(1-curalpha);
00447           alpha*=curalpha;
00448         }
00449       }
00450       if(sumcmd.weight>0) {
00451         sumcmd.value/=sumcmd.weight;
00452         outputs[frame][output]=sumcmd.value;
00453       } else //if zero weight, hold last value
00454         sumcmd.value=outputs[frame][output]=cmdSums[output];
00455       if(frame==NumFrames-1)
00456         cmds[output]=sumcmd;
00457     }
00458   
00459   for(uint output=0; output<NumOutputs; output++)
00460     cmdSums[output]=outputs[NumFrames-1][output];
00461         
00462   // now summarize each output's PID values (for those which use PID control)
00463   for(uint output=PIDJointOffset; output<PIDJointOffset+NumPIDJoints; output++) {
00464     cmdstatelist_t& curstatelist=cmdstates[output];
00465     float alpha=1;
00466     float sumpid[3];
00467     for(uint i=0; i<3; i++)
00468       sumpid[i]=0;
00469     float sumweight=0;
00470     cmdstatelist_t::index_t ent=curstatelist.begin();
00471     while(ent!=curstatelist.end() && alpha>0) {
00472       float tmppid[3];
00473       for(uint i=0; i<3; i++)
00474         tmppid[i]=0;
00475       float tmpweight=0;
00476       float curp=curstatelist[ent].priority;
00477       float curalpha=1; // curalpha is multiplicative sum of leftovers (weights between 0 and 1)
00478       for(;ent!=curstatelist.end() && curstatelist[ent].priority==curp; ent=curstatelist.next(ent)) {
00479         //weighted average within priority level
00480         float curweight=curstatelist[ent].pid.weight;
00481         ASSERT(curweight>=0,"negative PID weights are illegal")
00482         if(curweight<0) //negative weights are illegal
00483           curweight=0;
00484         for(uint i=0; i<3; i++)
00485           tmppid[i]+=curstatelist[ent].pid.pid[i]*curweight;
00486         tmpweight+=curweight;
00487         if(curweight<1)
00488           curalpha*=(1-curweight);
00489         else
00490           curalpha=0;
00491       }
00492       if(tmpweight>0) {
00493         //weighted average of priority levels
00494         for(uint i=0; i<3; i++)
00495           sumpid[i]+=tmppid[i]/tmpweight*(1-curalpha);
00496         sumweight+=(1-curalpha);
00497         alpha*=curalpha;
00498       }
00499     }
00500     if(sumweight>0) {
00501       for(uint i=0; i<3; i++)
00502         sumpid[i]/=sumweight;
00503       setPID(output,sumpid);
00504     }
00505   }
00506 
00507   func_end();
00508   //  if(begin(id)!=end())
00509   //if(state && state->buttons[LFrPawOffset]) cout << "getAngles-done." << flush;
00510 }
00511 
00512 void
00513 MotionManager::updateWorldState() {
00514   //cout << "updateWorldState" << endl;
00515   for(uint output=LEDOffset; output<LEDOffset+NumLEDs; output++)
00516     state->outputs[output]=cmdSums[output];
00517   for(uint output=BinJointOffset; output<BinJointOffset+NumBinJoints; output++)
00518     state->outputs[output]=cmdSums[output];
00519 
00520   // these parts check to see if there are "fake" joints, and sets their "sensed" values
00521   // to be the current target value, just in case a behavior is waiting for a non-existant
00522   // non-existant joint to move to a certain position.
00523   if(state->robotDesign & WorldState::ERS210Mask) {
00524     for(uint output=0; output<NumPIDJoints; output++)
00525       if(!ERS210Info::IsRealERS210[output])
00526         state->outputs[output]=cmdSums[output];
00527   } else if(state->robotDesign & WorldState::ERS220Mask) {
00528     for(uint output=0; output<NumPIDJoints; output++)
00529       if(!ERS220Info::IsRealERS220[output])
00530         state->outputs[output]=cmdSums[output];
00531   } else if(state->robotDesign & WorldState::ERS7Mask) {
00532     for(uint output=0; output<NumPIDJoints; output++)
00533       if(!ERS7Info::IsRealERS7[output])
00534         state->outputs[output]=cmdSums[output];
00535   } else
00536     cout << "MotionManager::updateWorldState() - could not detect model" << endl;
00537 }
00538 
00539 /*! This function handles the conversion from the Tekkotsu format (one
00540  *  regular IEEE float per parameter, to the OPEN-R format (which
00541  *  takes a specialized, reduced precision floating point number) This
00542  *  is all documented in PIDMC as well.
00543  *
00544  *  In order to send Tekkotsu's PIDs to the system, they are converted
00545  *  to the gain/shift format.  On the ERS-2xx, we could dynamically
00546  *  choose shift values to allow more precision in setting values.
00547  *
00548  *  With the ERS-7, all shifts are shared, so they must be set to a
00549  *  common set of values, defined by WorldState::DefaultPIDShifts.
00550  *  This limits the range of gains which can then be set.
00551  *
00552  *  Due to the mysterious warning which would occur with the 2xx,
00553  *  (AGRMSDriver::SetGain() : 0x0A IS USED FOR GAIN SHIFT VALUE.)  and
00554  *  since this seems to be the way things are going, all models now,
00555  *  by default, use global shift values (which can vary from model to
00556  *  model, just global for each model)
00557  *
00558  *  You can revert to the dynamic shift selection by commenting-in
00559  *  the noted code section below.
00560  *
00561  *  A final note: the OPENR::SetJointGain function seems to be
00562  *  a rather costly function call.  You should probably try to avoid
00563  *  setting PIDs at too high a frequency.
00564  */
00565 bool
00566 #ifdef PLATFORM_APERIOS
00567 MotionManager::updatePIDs(OPrimitiveID primIDs[NumOutputs]) {
00568 #else
00569 MotionManager::updatePIDs() {
00570 #endif
00571   //cout << "updatePIDs " << endl;
00572   bool dirty=!pidchanges.empty();
00573   while(!pidchanges.empty()) {
00574 #ifdef PLATFORM_APERIOS
00575     float gain[3];
00576     word shift[3];
00577 
00578     //if you want to enforce the default shifts:
00579     for(uint i=0; i<3; i++) {
00580       shift[i]=DefaultPIDShifts[i];
00581       gain[i]=pidchanges.front().pids[i]*(1<<(0x10-shift[i]));
00582     }
00583 
00584     //if you want to allow shifts to move for better precision:
00585     // this is OK on 2xx, although it occasionally produces warnings like:
00586     // AGRMSDriver::SetGain() : 0x0A IS USED FOR GAIN SHIFT VALUE.
00587     // It still seems to work fine though.
00588     // HOWEVER, the ERS-7 is a different story.  Apparently ( https://openr.aibo.com/cgi-bin/openr/e_regi/im_trbbs.cgi?uid=general&df=bbs.dat&prm=TAN&pg=1&no=0893#0893 )
00589     // all joints share the same shift, and so there must be one
00590     // global setting enforced.  If this is the way things are heading,
00591     // might as well just have everyone use the first method instead.
00592     // but here's the more dynamic way just for posterity:
00593     /*
00594     for(uint i=0; i<3; i++) {
00595       gain[i]=pidchanges.front().pids[i]*2;
00596       shift[i]=0xF;
00597       while(shift[i]!=2 && (gain[i]!=(word)gain[i] || gain[i]<=1) && gain[i]<0x20) {
00598         gain[i]*=2;
00599         shift[i]--;
00600       }
00601     }
00602     */
00603 
00604     //some debugging output (pick your favorite joint - i was having trouble with the ERS-7 nod joint in particular)
00605     //if(pidchanges.front().joint==HeadOffset+NodOffset)
00606     //cout << (word)gain[0] << ' ' << shift[0] << "   " << (word)gain[1] << ' ' << shift[1] << "   " << (word)gain[2] << ' ' << shift[2] << endl;
00607     //cout << gain[0] << ' ' << shift[0] << "   " << gain[1] << ' ' << shift[1] << "   " << gain[2] << ' ' << shift[2] << endl;
00608 
00609     OPENR::SetJointGain(primIDs[pidchanges.front().joint],(word)gain[0],(word)gain[1],(word)gain[2],shift[0],shift[1],shift[2]);
00610 #endif //PLATFORM_APERIOS or PLATFORM_LOCAL
00611     for(uint i=0; i<3; i++)
00612       state->pids[pidchanges.front().joint][i]=pidchanges.front().pids[i];
00613     pidchanges.pop_front();
00614   }
00615   return dirty;
00616 }
00617 
00618 #ifdef PLATFORM_APERIOS
00619 void
00620 MotionManager::receivedMsg(const ONotifyEvent& event) {
00621   //  cout << "receivedMsg..." << flush;
00622   func_begin();
00623   //  cout << id << "..." << flush;
00624   //cout << "Received at " << get_time() << endl;
00625   for(int x=0; x<event.NumOfData(); x++)
00626     processMsg(event.RCData(x));
00627   //  cout << "receivedMsg-done" << endl;
00628   func_end();
00629 }
00630 #else //PLATFORM_LOCAL
00631 bool
00632 MotionManager::receivedMsg(RCRegion* msg) {
00633   try {
00634     MarkScope l(*motman->procLocks[_MMaccID]);
00635     /*MotionManagerMsg * mminfo = reinterpret_cast<MotionManagerMsg*>(msg->Base());
00636     if(mminfo->creatorPID==ProcessID::getID())
00637       return true; //don't process echos*/
00638     motman->processMsg(msg);
00639   } catch(const std::exception& ex) {
00640     if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionManagerMsg processing (MotionManager::receivedMsg)",&ex))
00641       throw;
00642   } catch(...) {
00643     if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionManagerMsg processing (MotionManager::receivedMsg)",NULL))
00644       throw;
00645   }
00646   return true;
00647 }
00648 #endif //PLATFORM_APERIOS or PLATFORM_LOCAL
00649 
00650 void
00651 MotionManager::processMsg(RCRegion * rcr) {
00652   //cout << "processMsg..." << flush;
00653   if(rcr==NULL) {
00654     cout << "WARNING: MotionManager::processMsg was given a NULL region" << endl;
00655     return;
00656   }
00657   func_begin();
00658   //cout << ProcessID::getID() << "..." << flush;
00659   MotionManagerMsg * mminfo = reinterpret_cast<MotionManagerMsg*>(rcr->Base());
00660   MC_ID mc_id=mminfo->mc_id;
00661   if(mc_id==invalid_MC_ID) {
00662     //cout << "add message for already-deleted motion" << endl;
00663     func_end();
00664     return;
00665   }
00666   switch(mminfo->type) {
00667     case MotionManagerMsg::addMotion: {
00668       if(cmdlist[mc_id].rcr[_MMaccID]==NULL) {
00669         //cout << "receiveMotion()NOW: rcr->NumberOfReference()==" << rcr->NumberOfReference() << endl;
00670         cmdlist[mc_id].rcr[_MMaccID]=rcr;
00671         //cout << "receiveMotion(): rcr->NumberOfReference()==" << rcr->NumberOfReference() << endl;
00672         rcr->AddReference();
00673         //should be able to do a nice dynamic cast instead of a static one
00674         // but it gives NULL for some reason - i blame having to do the fork trick
00675         //cout << "Adding mc_id=="<< mc_id << " (and dynamic_cast is still " << dynamic_cast<MotionCommand*>(mminfo) << ")" << endl;
00676         cmdlist[mc_id].baseaddrs[_MMaccID]=static_cast<MotionCommand*>(mminfo);
00677       } else {
00678 #ifdef PLATFORM_APERIOS
00679         // this shouldn't happen on Aperios (no echos), but is normal elsewhere
00680         cerr << "WARNING: MotionManager::processMsg addMotion for motion which was already added!" << endl;
00681 #else
00682         ASSERT(cmdlist[mc_id].lastAccessor==(accID_t)-1 || cmdlist[mc_id].baseaddrs[_MMaccID]==static_cast<MotionCommand*>(mminfo),"Baseaddr changed!");
00683 #endif
00684       }
00685       if(ProcessID::getID()==ProcessID::MotionProcess && cmdlist[mc_id].lastAccessor!=(accID_t)-1) {
00686         checkoutMotion(mc_id,true);
00687         try {
00688           cmdlist[mc_id].baseaddrs[_MMaccID]->DoStart();
00689         } catch(const std::exception& ex) {
00690           ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionCommand DoStart()",&ex);
00691         } catch(...) {
00692           ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionCommand DoStart()",NULL);
00693         }
00694         checkinMotion(mc_id);
00695       }
00696     } break;
00697     case MotionManagerMsg::deleteMotion: {
00698       //cout << "deleteMotion(): cmdlist[mc_id].rcr[_MMaccID]->NumberOfReference()==" << cmdlist[mc_id].rcr[_MMaccID]->NumberOfReference() << endl;
00699       //cout << "deleting mc_id=="<<mc_id << "..." << flush;
00700       ASSERT(cmdlist[mc_id].lastAccessor==(accID_t)-1,"delete motion message for motion command not marked for deletion");
00701       if(cmdlist[mc_id].rcr[_MMaccID]==NULL) {
00702 #ifndef PLATFORM_APERIOS
00703         // on non-aperios, we get an echo of the remove request, so don't report an error, just ignore it
00704         if(mminfo->creatorPID!=ProcessID::getID()) {
00705 #endif
00706           cout << "WARNING: MotionManager attempted to delete a NULL motion! mc_id="<<mc_id<<" process=" << ProcessID::getIDStr() << endl;
00707           stacktrace::displayCurrentStackTrace();
00708 #ifndef PLATFORM_APERIOS
00709         }
00710 #endif
00711       } else {
00712         cmdlist[mc_id].lock.lock(_MMaccID);
00713         int found=0;
00714         for(unsigned int i=0; i<numAcc; i++) {
00715           if(cmdlist[mc_id].rcr[i]!=NULL) {
00716             found++;
00717           }
00718         }
00719         if(ProcessID::getID()==ProcessID::MotionProcess) {
00720           // no need to check out, motion should already be marked inaccessible from original call to removeMotion (as asserted at beginning of deleteMotion case)
00721           try {
00722             convertMotion(mc_id)->DoStop();
00723           } catch(const std::exception& ex) {
00724             ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionCommand DoStop()",&ex);
00725           } catch(...) {
00726             ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionCommand DoStop()",NULL);
00727           }
00728           cmdlist[mc_id].lastAccessor=(accID_t)-1; // reset inaccessiblity
00729         }
00730         cmdlist[mc_id].rcr[_MMaccID]->RemoveReference();
00731         cmdlist[mc_id].rcr[_MMaccID]=NULL;
00732         cmdlist[mc_id].baseaddrs[_MMaccID]=NULL;
00733         if(found==1) {
00734           push_free(mc_id); //don't unlock -- lock destructor will release the lock as the entry is destructed
00735         } else {
00736           cmdlist[mc_id].lock.unlock();
00737         }
00738         if(ProcessID::getID()==ProcessID::MainProcess) {
00739           try {
00740             erouter->postEvent(EventBase::motmanEGID,mc_id,EventBase::deactivateETID,0);
00741           } catch(const std::exception& ex) {
00742             ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during event posting",&ex);
00743           } catch(...) {
00744             ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during event posting",NULL);
00745           }
00746         }
00747       }
00748       //cout << "deleteMotion()NOW: cmdlist[mc_id].rcr[_MMaccID]->NumberOfReference()==" << cmdlist[mc_id].rcr[_MMaccID]->NumberOfReference() << endl;
00749     } break;
00750     default:
00751       printf("*** WARNING *** unknown MotionManager msg type received\n");
00752   }
00753   //cout << "processMsg-done" << endl;
00754   func_end();
00755 }
00756 
00757 
00758 /*! We have made this function protected because it's more readable if you
00759 *  call addPrunableMotion() or addPersistentMotion() instead... we decided
00760 *  requiring people to pass a true/false arguement wouldn't make it clear
00761 *  what that true/false was controlling. */
00762 MotionManager::MC_ID 
00763 MotionManager::doAddMotion(const SharedObjectBase& sm, bool autoprune, float priority) {
00764   MotionCommand * mc = dynamic_cast<MotionCommand*>(reinterpret_cast<MotionManagerMsg*>(sm.data()));
00765   if(mc==NULL) {
00766     cout << "MotionManager::addMotion() - SharedObject does not seem to hold a MotionCommand" << endl;
00767     return invalid_MC_ID;
00768   }
00769   mc->setAutoPrune(autoprune);
00770   //cout << "addMotion...";
00771   while(numAcc<MAX_ACCESS-1) { std::cout << "WAIT" << std::flush; } //Wait for everyone to register
00772   func_begin();
00773   //cout << cmdlist.size() << " exist..." << endl;
00774   //  cout << id << "..." << flush;
00775   for(MC_ID it=cmdlist.begin(); it!=cmdlist.end(); it=cmdlist.next(it)) {
00776     if(cmdlist[it].baseaddrs[_MMaccID]==mc) {
00777       cerr << "Warning: adding motion command at " << mc << ", is already running in motion manager as MC_ID " << it << endl;
00778       return func_end(it);
00779     }
00780   }
00781   MC_ID mc_id = pop_free();
00782   //cout << sm.getRegion()->ID().key << " holds " << mc_id << endl;
00783   if(mc_id==cmdlist.end()) {
00784     cout << "MotionManager::addMotion() - Out of room, could not add" << endl;
00785     return func_end(cmdlist.end());
00786   }
00787   //cout << "setAdd(" << mc_id << ")" << endl;
00788   mc->setAdd(mc_id);
00789   cmdlist[mc_id].baseaddrs[_MMaccID]=mc;
00790   cmdlist[mc_id].rcr[_MMaccID]=sm.getRegion();
00791   //cout << "addMotion(): sm.getRegion()->NumberOfReference()==" << sm.getRegion()->NumberOfReference() << endl;
00792   cmdlist[mc_id].rcr[_MMaccID]->AddReference();
00793   //cout << "addMotion()NOW: sm.getRegion()->NumberOfReference()==" << sm.getRegion()->NumberOfReference() << endl;
00794   cmdlist[mc_id].lastAccessor=_MMaccID;
00795   cmdlist[mc_id].priority=priority;
00796   try {
00797     erouter->postEvent(EventBase::motmanEGID,mc_id,EventBase::activateETID,0);
00798   } catch(const std::exception& ex) {
00799     ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during event posting",&ex);
00800   } catch(...) {
00801     ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during event posting",NULL);
00802   }
00803   
00804 #ifdef PLATFORM_APERIOS
00805   OStatus err;
00806   /*{
00807     unsigned int i=0;
00808     for(ObserverConstIterator it=subjs[_MMaccID]->begin();it!=subjs[_MMaccID]->end();it++) {
00809       cout << "RemainBuffer("<<i++<<")==" << subjs[_MMaccID]->RemainBuffer(*it) << endl;
00810     }
00811     ASSERT((int)i==subjs[_MMaccID]->NumberOfObservers(),"did I miss an observer?");
00812   }*/
00813   //cout << "Sent at " << get_time() << flush;
00814   err=subjs[_MMaccID]->SetData(sm.getRegion());
00815   ASSERT(err==oSUCCESS,"*** ERROR MotionManager: SetData returned " << err);
00816   //cout << "addMotion()afterSetData: sm.getRegion()->NumberOfReference()==" << sm.getRegion()->NumberOfReference() << endl;
00817   err=subjs[_MMaccID]->NotifyObservers();
00818   ASSERT(err==oSUCCESS,"*** ERROR MotionManager: NotifyObservers returned " << err);
00819 #else //PLATFORM_LOCAL
00820   try {
00821     subjs[_MMaccID]->sendMessage(sm.getRegion());
00822   } catch(const std::exception& ex) {
00823     ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during message sending",&ex);
00824   } catch(...) {
00825     ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during message sending",NULL);
00826   }
00827 #endif //PLATFORM check for IPC stuff
00828   //  cout << "addMotion-done" << endl;
00829   //cout << " - " << get_time() << endl;
00830   return func_end(mc_id);
00831 }
00832 
00833 MotionCommand *
00834 MotionManager::checkoutMotion(MC_ID mcid,bool block) {
00835   //cout << "checkout..." << flush;
00836   if(mcid>=MAX_MOTIONS || mcid==invalid_MC_ID) {
00837     cout << "*** WARNING *** " << ProcessID::getIDStr() << " tried to access invalid mcid " << mcid << endl;
00838     stacktrace::displayCurrentStackTrace();
00839     return NULL;
00840   }
00841   if(block)
00842     cmdlist[mcid].lock.lock(_MMaccID);
00843   else
00844     if(!cmdlist[mcid].lock.try_lock(_MMaccID))
00845       return NULL;
00846   if(cmdlist[mcid].lastAccessor==(accID_t)-1) {
00847     cout << "*** WARNING *** " << ProcessID::getIDStr() << " tried to access dead mcid " << mcid << endl;
00848     stacktrace::displayCurrentStackTrace();
00849     cmdlist[mcid].lock.unlock();
00850     return NULL;
00851   }
00852   //cout << "locked..." << endl;
00853   //cout << "checkout-done..." << flush;
00854   return convertMotion(mcid);
00855 }
00856 
00857 MotionCommand *
00858 MotionManager::convertMotion(MC_ID mc) {
00859   MotionCommand * base = cmdlist[mc].baseaddrs[_MMaccID];
00860   //  cout << "base=" << base << "..." << flush;
00861   if(cmdlist[mc].lastAccessor!=_MMaccID) {
00862     //cout << "converting from " << MCRegistrar::getRaw(base) << "..." << flush;
00863     //cout << "prev=" << accRegs[cmdlist[mcid].lastAccessor].getReg(base) << "..." << flush;
00864     //    accRegs[id].convert(base);
00865     //cout << "to=" << MCRegistrar::getRaw(base) << ", " << accRegs[cmdlist[mcid].lastAccessor].getReg(base) << endl;
00866     cmdlist[mc].lastAccessor=_MMaccID;
00867   }
00868   base->setTranslator(etrans);
00869 #ifdef PLATFORM_APERIOS
00870   base->setWorldState(state);
00871 #endif
00872   return base;
00873 }
00874 
00875 void
00876 MotionManager::checkinMotion(MC_ID mcid) {
00877   if(mcid>=MAX_MOTIONS || mcid==invalid_MC_ID)
00878     return;
00879   if(cmdlist[mcid].lock.get_lock_level()==1 && cmdlist[mcid].rcr[_MMaccID]!=NULL) { //about to release last lock (and region hasn't been removed)
00880     MotionCommand * base = cmdlist[mcid].baseaddrs[_MMaccID];
00881     base->setTranslator(NULL);
00882 #ifdef PLATFORM_APERIOS
00883     base->setWorldState(NULL);
00884 #endif
00885   }
00886   cmdlist[mcid].lock.unlock();
00887 }
00888 
00889 void
00890 MotionManager::removeMotion(MC_ID mcid) {
00891   if(mcid>=MAX_MOTIONS || mcid==invalid_MC_ID)
00892     return;
00893   func_begin();
00894   if(cmdlist[mcid].lastAccessor==(accID_t)-1) {
00895     cout << "WARNING: removeMotion called for a motion which has already been removed mc_id="<<mcid<<" process=" << ProcessID::getIDStr() << endl;
00896     stacktrace::displayCurrentStackTrace();
00897     func_end();
00898     return;
00899   }
00900   if(cmdlist[mcid].rcr[_MMaccID]==NULL) { 
00901     cout << "WARNING: removeMotion called for a NULL motion! mc_id="<<mcid<<" process=" << ProcessID::getIDStr() << endl;
00902     stacktrace::displayCurrentStackTrace();
00903     func_end();
00904     return;
00905   }
00906   cmdlist[mcid].lock.lock(_MMaccID);
00907   if(ProcessID::getID()==ProcessID::MotionProcess) {
00908     MotionCommand * mc=checkoutMotion(mcid,true);
00909     try {
00910       mc->DoStop();
00911     } catch(const std::exception& ex) {
00912       ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionCommand DoStop()",&ex);
00913     } catch(...) {
00914       ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionCommand DoStop()",NULL);
00915     }
00916     checkinMotion(mcid);
00917   }
00918   cmdlist[mcid].lastAccessor=(accID_t)-1;
00919   cmdlist[mcid].rcr[_MMaccID]->RemoveReference();
00920   cmdlist[mcid].rcr[_MMaccID]=NULL;
00921   cmdlist[mcid].baseaddrs[_MMaccID]=NULL;
00922   cmdlist[mcid].lock.unlock();
00923   if(ProcessID::getID()==ProcessID::MainProcess) {
00924     try {
00925       erouter->postEvent(EventBase::motmanEGID,mcid,EventBase::deactivateETID,0);
00926     } catch(const std::exception& ex) {
00927       ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during event posting",&ex);
00928     } catch(...) {
00929       ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during event posting",NULL);
00930     }
00931   }
00932 #ifdef PLATFORM_APERIOS
00933   MotionManagerMsg dmsg;
00934   dmsg.setDelete(mcid);
00935   //cout << "Remove at " << get_time() << flush;
00936   subjs[_MMaccID]->SetData(&dmsg,sizeof(dmsg));
00937   subjs[_MMaccID]->NotifyObservers();
00938 #else //PLATFORM_LOCAL
00939   // local will "echo" the message, so we'll do the actual remove when we get the echo
00940   SharedObject<MotionManagerMsg> dmsg;
00941   dmsg->setDelete(mcid);
00942   //cout << "Remove at " << get_time() << flush;
00943   try {
00944     subjs[_MMaccID]->sendMessage(dmsg.getRegion());
00945   } catch(const std::exception& ex) {
00946     ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during message sending",&ex);
00947   } catch(...) {
00948     ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during message sending",NULL);
00949   }
00950 #endif //PLATFORM check for IPC stuff
00951   func_end();
00952 }
00953 
00954 
00955 /*! Note that we don't actually set the PIDs in the system here, we just queue them up.
00956  *  PID changes seem to be an expensive operation, so may only want to clear the queue
00957  *  at some reduced rate (although that's not actually currently being done, it just
00958  *  could be) */
00959 void
00960 MotionManager::setPID(unsigned int joint, const float pids[3]) {
00961   func_begin();
00962 
00963   //see if there's already an update for this joint
00964   for(uint u = pidchanges.begin(); u!=pidchanges.end(); u=pidchanges.next(u)) {
00965     if(pidchanges[u].joint==joint) { //found it
00966       for(uint i=0; i<3; i++) {
00967         pidchanges[u].pids[i]=pids[i];
00968         if(pids[i]!=state->pids[joint][i]) { //see if we're setting back to current PID
00969           for(i++; i<3; i++) //we aren't, copy over the rest
00970             pidchanges[u].pids[i]=pids[i];
00971           func_end();
00972           return;
00973         }
00974       }
00975       //if it didn't return within the loop, no difference was found from current state
00976       //so just delete the update
00977       pidchanges.erase(u);
00978       func_end();
00979       return;
00980     }
00981   }
00982 
00983   //if we completed the for loop, we didn't find an update for the joint
00984   for(uint i=0; i<3; i++) //check to see if it's different from the current
00985     if(pids[i]!=state->pids[joint][i]) {
00986       PIDUpdate update(joint,pids); //it is different, insert a new update
00987       pidchanges.push_back(update);
00988       // or for debugging:
00989       //ListMemBuf<PIDUpdate,NumPIDJoints>::index_t it=pidchanges.push_back(update);
00990       //ASSERT(it!=pidchanges.end(),"MotionManager ran out of pidchanges entries!");
00991       break;
00992     }
00993   func_end();
00994 }
00995 
00996 
00997 MotionManager::MC_ID
00998 MotionManager::skip_ahead(MC_ID mcid) const {
00999   // this is in case a new motion has been added, but the current
01000   // process hasn't received its own copy yet, so should skip over them
01001   while(mcid!=cmdlist.end() && cmdlist[mcid].rcr[_MMaccID]==NULL)
01002     mcid=cmdlist.next(mcid);
01003   return mcid;
01004 }
01005 
01006 MotionManager::OutputState::OutputState()
01007   : priority(0),mcid(MotionManager::invalid_MC_ID), pid()
01008 {}
01009 MotionManager::OutputState::OutputState(unsigned int out, float pri, MC_ID mc, const OutputCmd cmds[NumFrames])
01010   : priority(pri),mcid(mc), pid(DefaultPIDs[out])
01011 {
01012   for(unsigned int i=0; i<NumFrames; i++)
01013     frames[i]=cmds[i];
01014 }
01015 MotionManager::OutputState::OutputState(unsigned int out, float pri, MC_ID mc, const OutputCmd& cmd)
01016   : priority(pri),mcid(mc), pid(DefaultPIDs[out])
01017 {
01018   for(unsigned int i=0; i<NumFrames; i++)
01019     frames[i]=cmd;
01020 }
01021 MotionManager::OutputState::OutputState(unsigned int out, float pri, MC_ID mc, const OutputCmd& cmd, unsigned int frame)
01022   : priority(pri),mcid(mc), pid(DefaultPIDs[out])
01023 {
01024   frames[frame]=cmd;
01025 }
01026 MotionManager::OutputState::OutputState(unsigned int /*out*/, float pri, MC_ID mc, const OutputPID& p)
01027   : priority(pri),mcid(mc), pid(p)
01028 {}
01029 MotionManager::OutputState::OutputState(unsigned int /*out*/, float pri, MC_ID mc, const OutputCmd cmds[NumFrames], const OutputPID& p)
01030   : priority(pri),mcid(mc), pid(p)
01031 {
01032   for(unsigned int i=0; i<NumFrames; i++)
01033     frames[i]=cmds[i];
01034 }
01035 MotionManager::OutputState::OutputState(unsigned int /*out*/, float pri, MC_ID mc, const OutputCmd& cmd, const OutputPID& p)
01036   : priority(pri),mcid(mc), pid(p)
01037 {
01038   for(unsigned int i=0; i<NumFrames; i++)
01039     frames[i]=cmd;
01040 }
01041 
01042 
01043 /*! @file
01044  * @brief Implements MotionManager, simplifies sharing of MotionCommand's and provides mutual exclusion to their access
01045  * @author ejt (Creator)
01046  *
01047  * $Author: ejt $
01048  * $Name: tekkotsu-3_0 $
01049  * $Revision: 1.61 $
01050  * $State: Exp $
01051  * $Date: 2006/09/25 23:30:16 $
01052  */
01053 
01054 
01055 /*
01056     for(uint f=0;f<NumFrames;f++)
01057       for(uint i=0; i<NumOutputs; i++)
01058         outputs[f][i]=0;
01059     const uint cyctime=128;
01060     uint ot=get_time()+3*cyctime;
01061     for(uint f=0;f<NumFrames;f++) {
01062       uint t=ot+f*FrameTime;
01063       outputs[f][TopBrLEDOffset]=(t/(double)cyctime-t/cyctime)*.75+.25;
01064       t-=cyctime;
01065       outputs[f][TopLLEDOffset]=(t/(double)cyctime-t/cyctime)*.75+.25;
01066       outputs[f][TopRLEDOffset]=(t/(double)cyctime-t/cyctime)*.75+.25;
01067       t-=cyctime;
01068       outputs[f][MidLLEDOffset]=(t/(double)cyctime-t/cyctime)*.75+.25;
01069       outputs[f][MidRLEDOffset]=(t/(double)cyctime-t/cyctime)*.75+.25;
01070       t-=cyctime;
01071       outputs[f][BotLLEDOffset]=(t/(double)cyctime-t/cyctime)*.75+.25;
01072       outputs[f][BotRLEDOffset]=(t/(double)cyctime-t/cyctime)*.75+.25;
01073     }
01074 */
01075 
01076   /*  for(uint output=TlRedLEDOffset-1; output<LEDOffset+NumLEDs-1; output++) {
01077     cmdstatelist_t& curstatelist=cmdstates[output];
01078     cout << "Out " << output << ": ";
01079     for(cmdstatelist_t::index_t bit=curstatelist.begin(); bit!=curstatelist.end(); bit=curstatelist.next(bit))
01080       cout << '('<<curstatelist[bit].mcid<<','<<cmdlist[curstatelist[bit].mcid].priority<<','<<curstatelist[bit].frames[0].value<<','<<curstatelist[bit].frames[0].weight<<") ";
01081     cout << endl;
01082     }*/
01083 
01084 
01085   /*  cout << get_time() << ' ' << size() << endl;
01086   for(uint output=TlRedLEDOffset; output<LEDOffset+NumLEDs-1; output++) {
01087     cmdstatelist_t& curstatelist=cmdstates[output];
01088     cout << "Out " << output << ": ";
01089     for(cmdstatelist_t::index_t bit=curstatelist.begin(); bit!=curstatelist.end(); bit=curstatelist.next(bit))
01090       cout << '('<<curstatelist[bit].mcid<<','<<cmdlist[curstatelist[bit].mcid].priority<<','<<curstatelist[bit].frames[0].value<<','<<curstatelist[bit].frames[0].weight<<") ";
01091     cout << endl;
01092   }
01093   */

Tekkotsu v3.0
Generated Wed Oct 4 00:03:44 2006 by Doxygen 1.4.7