00001 #include "MotionManager.h"
00002 #include "MotionCommand.h"
00003 #include "Events/EventRouter.h"
00004 #include "Shared/StackTrace.h"
00005 #include "Shared/ProjectInterface.h"
00006 #include "Shared/debuget.h"
00007 #include "Shared/WorldState.h"
00008 #include "IPC/SharedObject.h"
00009 
00010 #ifndef PLATFORM_APERIOS
00011 #  include "IPC/MessageQueue.h"
00012 #  include "IPC/MessageReceiver.h"
00013 #  include "Shared/ProjectInterface.h"
00014 #endif
00015 
00016 #include "Shared/ERS210Info.h"
00017 #include "Shared/ERS220Info.h"
00018 #include "Shared/ERS7Info.h"
00019 #include "Shared/Config.h"
00020 
00021 #include <list>
00022 
00023 MotionManager * motman=NULL;
00024 int MotionManager::_MMaccID[ProcessID::NumProcesses];
00025 EventTranslator* MotionManager::etrans=NULL;
00026 
00027 const float MotionManager::kIgnoredPriority    =-1;
00028 const float MotionManager::kBackgroundPriority = 0;
00029 const float MotionManager::kLowPriority        = 5;
00030 const float MotionManager::kStdPriority        = 10;
00031 const float MotionManager::kHighPriority       = 50;
00032 const float MotionManager::kEmergencyPriority  = 100;
00033 
00034 using namespace std;
00035 
00036 
00037 typedef unsigned int uint;
00038 
00039 MotionManager::MotionManager()
00040 : pidchanges(),cmdlist(),cur_cmd(invalid_MC_ID),MMlock(),numAcc(0)
00041 {
00042   for(uint x=0; x<NumOutputs; x++)
00043     cmdSums[x]=0;
00044 }
00045 
00046 #ifdef PLATFORM_APERIOS
00047 
00048 void
00049 MotionManager::InitAccess(OSubject* subj) {
00050   if(numAcc==MAX_ACCESS) {
00051     printf("*** ERROR *** attempted to register more accessors with MotionManager than allowed by MAX_ACCESS\n");
00052     return;
00053   }
00054   _MMaccID[ProcessID::getID()]=numAcc++;
00055   
00056   MMlock.lock(getAccID());
00057   
00058   subjs[getAccID()]=subj;
00059   if(cmdlist.size()>0) 
00060     cout << "*** WARNING *** MOTIONS ADDED BEFORE ALL INITACCESSED" << endl;
00061   MMlock.unlock();
00062 }
00063 
00064 #else //now PLATFORM_LOCAL
00065 
00066 void
00067 MotionManager::InitAccess(MessageQueueBase& mcbufq, Resource& behaviorLock) {
00068   if(numAcc==MAX_ACCESS) {
00069     printf("*** ERROR *** attempted to register more accessors with MotionManager than allowed by MAX_ACCESS\n");
00070     return;
00071   }
00072   _MMaccID[ProcessID::getID()]=numAcc++;
00073   
00074   MMlock.lock(getAccID());
00075   subjs[getAccID()]=&mcbufq;
00076   mcrecvs[getAccID()]=new MessageReceiver(*subjs[getAccID()],receivedMsg);
00077   procLocks[getAccID()]=&behaviorLock;
00078   if(cmdlist.size()>0) 
00079     cout << "*** WARNING *** MOTIONS ADDED BEFORE ALL INITACCESSED" << endl;
00080   MMlock.unlock();
00081 }
00082 
00083 #endif //PLATFORM-specific initialization
00084 
00085 void
00086 MotionManager::RemoveAccess() {
00087 #ifndef PLATFORM_APERIOS
00088   
00089   
00090   mcrecvs[getAccID()]->finish();
00091   delete mcrecvs[getAccID()];
00092   mcrecvs[getAccID()]=NULL;
00093 #endif
00094   
00095   func_begin();
00096   for(MC_ID mc_id=cmdlist.begin(); mc_id!=cmdlist.end(); mc_id=cmdlist.next(mc_id)) {
00097     if(cmdlist[mc_id].rcr[getAccID()]!=NULL) {
00098       MotionCommand* mc=checkoutMotion(mc_id,true);
00099       int found=0;
00100       for(unsigned int i=0; i<numAcc; i++) {
00101         if(cmdlist[mc_id].rcr[i]!=NULL) {
00102           found++;
00103         }
00104       }
00105       cout << "Warning: " << ProcessID::getIDStr() << " dropping motion command " << mc_id << " of type " << typeid(*mc).name() << ", was active at shutdown " << (mc->getAutoPrune()?"(was set for autoprune)":"(leaked?)") << '\n';
00106       cout << "         Motion command " << mc_id << " was created from:" << endl;
00107       stacktrace::displayStackTrace(cmdlist[mc_id].trace);
00108 #ifdef PLATFORM_APERIOS
00109       int refs=1;
00110 #else
00111       int refs=cmdlist[mc_id].rcr[getAccID()]->NumberOfLocalReference();
00112 #endif
00113       if(refs>1)
00114         cout << "Warning: " << ProcessID::getIDStr() << " still had " <<  refs-1 << " references to motion command " << mc_id << " as it was being dropped (these are now invalid)" << endl;
00115       for(int i=0; i<refs; ++i)
00116         cmdlist[mc_id].rcr[getAccID()]->RemoveReference();
00117       cmdlist[mc_id].rcr[getAccID()]=NULL;
00118       if(found==1) {
00119         MC_ID p=cmdlist.prev(mc_id);
00120         push_free(mc_id); 
00121         mc_id=p;
00122       } else {
00123         checkinMotion(mc_id);
00124       }
00125     }
00126   }
00127   func_end();
00128 }
00129 
00130 
00131 MotionManager::~MotionManager() {
00132   if(!cmdlist.empty()) {
00133     func_begin();
00134     cout << "WARNING: MotionManager destruction with MotionCommands still attached." << endl;
00135     while(!cmdlist.empty()) {
00136       MC_ID mc_id=cmdlist.begin();
00137       for(unsigned int i=0; i<numAcc; i++)
00138         if(cmdlist[mc_id].rcr[i]!=NULL)
00139           cout << "MC " << mc_id << " was still referenced by InitAccess caller #" << getAccID() << endl;
00140       push_free(mc_id);
00141     }
00142     func_end();
00143   }
00144 }
00145 
00146 
00147 void
00148 MotionManager::motionReport() const {
00149   func_begin();
00150   std::cout << cmdlist.size() << " live motion commands\n";
00151   for(MC_ID mc_id=cmdlist.begin(); mc_id!=cmdlist.end(); mc_id=cmdlist.next(mc_id)) {
00152     MotionCommand* mc=checkoutMotion(mc_id,true);
00153     std::cout << "MC_ID " << mc_id << " type " << typeid(*mc).name() << " priority " << cmdlist[mc_id].priority << '\n';
00154     std::cout << "Created by:" << std::endl;
00155     stacktrace::displayStackTrace(cmdlist[mc_id].trace);
00156     checkinMotion(mc_id);
00157   }
00158   std::cout << "\nOutput Usage: (MCID @ value [* weight])\n";
00159   bool any=false;
00160   for(unsigned int i=0; i<NumOutputs; ++i) {
00161     bool first=true;
00162     for(unsigned int j=cmdstates[i].begin(); j!=cmdstates[i].end(); j=cmdstates[i].next(j)) {
00163       if(cmdstates[i][j].frames[NumFrames-1].weight > 0) {
00164         if(first) {
00165           std::cout << "   " << outputNames[i] << ':';
00166           first=false;
00167           any=true;
00168         }
00169         std::cout << " (" << cmdstates[i][j].mcid << " @ " << cmdstates[i][j].frames[NumFrames-1].value;
00170         if(cmdstates[i][j].frames[NumFrames-1].weight!=1)
00171           std::cout << " * " << cmdstates[i][j].frames[NumFrames-1].weight;
00172         std::cout << ")";
00173       }
00174     }
00175     if(!first)
00176       std::cout << '\n';
00177   }
00178   if(!any)
00179     std::cout << "   [No outputs in use]" << std::endl;
00180   func_end();
00181 }
00182 
00183 
00184 void
00185 MotionManager::setOutput(const MotionCommand* caller, unsigned int output, const OutputCmd& cmd) {
00186   if(output >= NumOutputs)
00187     return;
00188   if(cmd.weight<=0)
00189     return;
00190 
00191   if(caller==NULL || caller->getID()!=cur_cmd)
00192     func_begin();
00193   if(cur_cmd==invalid_MC_ID) {
00194     cmdSums[output]=cmd.value;
00195   } else if(getPriority(cur_cmd)>=kBackgroundPriority) {
00196     cmdstatelist_t& curstatelist=cmdstates[output];
00197     cmdstatelist_t::index_t ent=curstatelist.begin();
00198     if(ent==curstatelist.end() || curstatelist[ent].mcid!=cur_cmd)
00199       curstatelist.push_front(OutputState(output,getPriority(cur_cmd),cur_cmd,cmd));
00200     else
00201       for(unsigned int i=0; i<NumFrames; i++)
00202         curstatelist[ent].frames[i]=cmd;
00203   }
00204   if(caller==NULL || caller->getID()!=cur_cmd)
00205     func_end();
00206 }
00207 
00208 void
00209 MotionManager::setOutput(const MotionCommand* caller, unsigned int output, const OutputCmd& cmd, unsigned int frame) {
00210   if(output >= NumOutputs)
00211     return;
00212   if(cmd.weight<=0)
00213     return;
00214 
00215   if(caller==NULL || caller->getID()!=cur_cmd)
00216     func_begin();
00217   if(cur_cmd==invalid_MC_ID) {
00218     cmdSums[output]=cmd.value;
00219   } else if(getPriority(cur_cmd)>=kBackgroundPriority) {
00220     cmdstatelist_t& curstatelist=cmdstates[output];
00221     cmdstatelist_t::index_t ent=curstatelist.begin();
00222     if(ent==curstatelist.end() || curstatelist[ent].mcid!=cur_cmd)
00223       curstatelist.push_front(OutputState(output,getPriority(cur_cmd),cur_cmd,cmd,frame));
00224     else
00225       curstatelist[ent].frames[frame]=cmd;
00226   }
00227   if(caller==NULL || caller->getID()!=cur_cmd)
00228     func_end();
00229 }
00230 
00231 void 
00232 MotionManager::setOutput(const MotionCommand* caller, unsigned int output, const OutputCmd ocmds[NumFrames]) {
00233   if(output >= NumOutputs)
00234     return;
00235   unsigned int hasWeight=NumFrames;
00236   for(unsigned int i=NumFrames-1; i!=-1U; i--)
00237     if(ocmds[i].weight>0) {
00238       hasWeight=i;
00239       break;
00240     }
00241   if(hasWeight==NumFrames)
00242     return;
00243   
00244 
00245   if(caller==NULL || caller->getID()!=cur_cmd)
00246     func_begin();
00247   if(cur_cmd==invalid_MC_ID) {
00248     cmdSums[output]=ocmds[hasWeight].value;
00249   } else if(getPriority(cur_cmd)>=kBackgroundPriority) {
00250     cmdstatelist_t& curstatelist=cmdstates[output];
00251     cmdstatelist_t::index_t ent=curstatelist.begin();
00252     if(ent==curstatelist.end() || curstatelist[ent].mcid!=cur_cmd)
00253       curstatelist.push_front(OutputState(output,getPriority(cur_cmd),cur_cmd,ocmds));
00254     else
00255       for(unsigned int i=0; i<NumFrames; i++)
00256         curstatelist[ent].frames[i]=ocmds[i];
00257   }
00258   if(caller==NULL || caller->getID()!=cur_cmd)
00259     func_end();
00260 }
00261 
00262 void
00263 MotionManager::setOutput(const MotionCommand* caller, unsigned int output, const OutputPID& pid) {
00264   if(output >= NumOutputs)
00265     return;
00266 
00267   if(caller==NULL || caller->getID()!=cur_cmd)
00268     func_begin();
00269   if(cur_cmd==invalid_MC_ID) {
00270     setPID(output,pid.pid);
00271   } else if(getPriority(cur_cmd)>=kBackgroundPriority) {
00272     cmdstatelist_t& curstatelist=cmdstates[output];
00273     cmdstatelist_t::index_t ent=curstatelist.begin();
00274     if(ent==curstatelist.end() || curstatelist[ent].mcid!=cur_cmd)
00275       curstatelist.push_front(OutputState(output,getPriority(cur_cmd),cur_cmd,pid));
00276     else
00277       curstatelist[ent].pid=pid;
00278   }
00279   if(caller==NULL || caller->getID()!=cur_cmd)
00280     func_end();
00281 }
00282 
00283 void
00284 MotionManager::setOutput(const MotionCommand* caller, unsigned int output, const OutputCmd& cmd, const OutputPID& pid) {
00285   if(output >= NumOutputs)
00286     return;
00287 
00288   if(caller==NULL || caller->getID()!=cur_cmd)
00289     func_begin();
00290   if(cur_cmd==invalid_MC_ID) {
00291     if(cmd.weight>0)
00292       cmdSums[output]=cmd.value;
00293     setPID(output,pid.pid);
00294   } else if(getPriority(cur_cmd)>=kBackgroundPriority) {
00295     cmdstatelist_t& curstatelist=cmdstates[output];
00296     cmdstatelist_t::index_t ent=curstatelist.begin();
00297     if(ent==curstatelist.end() || curstatelist[ent].mcid!=cur_cmd)
00298       curstatelist.push_front(OutputState(output,getPriority(cur_cmd),cur_cmd,cmd,pid));
00299     else {
00300       for(unsigned int i=0; i<NumFrames; i++)
00301         curstatelist[ent].frames[i]=cmd;
00302       curstatelist[ent].pid=pid;
00303     }
00304   }
00305   if(caller==NULL || caller->getID()!=cur_cmd)
00306     func_end();
00307 }
00308 
00309 void
00310 MotionManager::setOutput(const MotionCommand* caller, unsigned int output, const OutputCmd ocmds[NumFrames], const OutputPID& pid) {
00311   if(output >= NumOutputs)
00312     return;
00313 
00314   if(caller==NULL || caller->getID()!=cur_cmd)
00315     func_begin();
00316   if(cur_cmd==invalid_MC_ID) {
00317     if(ocmds[NumFrames-1].weight>0)
00318       cmdSums[output]=ocmds[NumFrames-1].value;
00319     setPID(output,pid.pid);
00320   } else if(getPriority(cur_cmd)>=kBackgroundPriority) {
00321     cmdstatelist_t& curstatelist=cmdstates[output];
00322     cmdstatelist_t::index_t ent=curstatelist.begin();
00323     if(ent==curstatelist.end() || curstatelist[ent].mcid!=cur_cmd)
00324       curstatelist.push_front(OutputState(output,getPriority(cur_cmd),cur_cmd,ocmds,pid));
00325     else {
00326       for(unsigned int i=0; i<NumFrames; i++)
00327         curstatelist[ent].frames[i]=ocmds[i];
00328       curstatelist[ent].pid=pid;
00329     }
00330   }
00331   if(caller==NULL || caller->getID()!=cur_cmd)
00332     func_end();
00333 }
00334 
00335 
00336 
00337 
00338 void
00339 MotionManager::getOutputs(float outputs[][NumOutputs]) {
00340   
00341   
00342   if(state==NULL) {
00343     
00344     for(uint f=0;f<NumFrames;f++)
00345       for(uint i=0; i<NumOutputs; i++)
00346         outputs[f][i]=0;
00347     for(uint f=0;f<NumFrames;f++)
00348       for(uint l=0; l<NumLEDs; l++)
00349         outputs[f][l]=l/(NumLEDs-1.0f);
00350     
00351     
00352     return;
00353   }
00354   func_begin();
00355   
00356   
00357   
00358   for(uint output=0; output<NumOutputs; output++)
00359     cmdstates[output].clear();
00360 
00361   
00362   
00363   
00364   
00365   
00366   
00367   
00368   
00369   
00370   
00371   
00372   for(uint output=0; output<NumPIDJoints; output++)
00373     if(state->pids[output][0]==0 && state->pids[output][1]==0 && state->pids[output][2]==0)
00374       cmdSums[output]=state->outputs[output];
00375 
00376   
00377   std::list<MC_ID> unlocked;
00378   for(MC_ID mcNum=begin(); mcNum!=end(); mcNum=next(mcNum)) 
00379     if(cmdlist[mcNum].lastAccessor!=(accID_t)-1)
00380       unlocked.push_back(mcNum);
00381   unsigned int lastProcessed=get_time();
00382   while(unlocked.size()>0) { 
00383     for(std::list<MC_ID>::iterator it=unlocked.begin(); it!=unlocked.end(); ) {
00384       MotionCommand* mc=checkoutMotion(*it,false);
00385       if(mc==NULL)
00386         it++; 
00387       else {
00388         
00389         cur_cmd=*it;
00390         bool prune=true;
00391         try {
00392           prune=mc->shouldPrune();
00393         } catch(const std::exception& ex) {
00394           ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionCommand prune test, will prune",&ex);
00395         } catch(...) {
00396           ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionCommand prune test, will prune",NULL);
00397         }
00398         if(prune) {
00399           
00400           checkinMotion(*it); 
00401           
00402           
00403           
00404           removeMotion(*it);
00405         } else {
00406           try {
00407             if ( cmdlist[mc->getID()].priority >= kBackgroundPriority )
00408               mc->updateOutputs(); 
00409           } catch(const std::exception& ex) {
00410             ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionCommand updateOutputs",&ex);
00411           } catch(...) {
00412             ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionCommand updateOutputs",NULL);
00413           }
00414           checkinMotion(*it); 
00415         }
00416         cur_cmd=invalid_MC_ID;
00417         
00418         std::list<MC_ID>::iterator rem=it++;
00419         unlocked.erase(rem);
00420         lastProcessed=get_time();
00421       }
00422     }
00423     if(get_time()-lastProcessed>FrameTime*NumFrames/2)
00424       break;
00425   }
00426   
00427 
00428 
00429 
00430 
00431 
00432 
00433 
00434 
00435 
00436 
00437   
00438   
00439   for(uint output=0; output<NumOutputs; output++) {
00440     cmdstatelist_t& curstatelist=cmdstates[output];
00441     for(cmdstatelist_t::index_t bit=curstatelist.begin(); bit!=curstatelist.end(); bit=curstatelist.next(bit)) {
00442       MC_ID high_ent=bit;
00443       float high_p=cmdlist[curstatelist[high_ent].mcid].priority;
00444       for(cmdstatelist_t::index_t cit=curstatelist.next(bit); cit!=curstatelist.end(); cit=curstatelist.next(cit)) {
00445         float curp=cmdlist[curstatelist[cit].mcid].priority;
00446         if(curp>high_p) {
00447           high_p=curp;
00448           high_ent=cit;
00449         }
00450       }
00451       curstatelist.swap(bit,high_ent);
00452       
00453 
00454 
00455 
00456       bit=high_ent;
00457     }
00458   }
00459 
00460   
00461   
00462   for(uint frame=0; frame<NumFrames; frame++) {
00463     for(uint output=0; output<NumOutputs; output++) {
00464       cmdstatelist_t& curstatelist=cmdstates[output];
00465       float alpha=1;
00466       OutputCmd sumcmd;
00467       
00468 
00469 
00470 
00471 
00472 
00473       cmdstatelist_t::index_t ent=curstatelist.begin();
00474       while(ent!=curstatelist.end() && alpha>0) {
00475         OutputCmd curcmd;
00476         float curp=curstatelist[ent].priority;
00477         float curalpha=1; 
00478         for(;ent!=curstatelist.end() && curstatelist[ent].priority==curp; ent=curstatelist.next(ent)) {
00479           
00480           float curweight=curstatelist[ent].frames[frame].weight;
00481           ASSERT(curweight>=0,"negative output weights are illegal, MC_ID="<<curstatelist[ent].mcid<<" joint="<<outputNames[output]<<" frame="<<frame<<" weight="<<curweight);
00482           if(curweight<0) 
00483             curweight=0;
00484           curcmd.value+=curstatelist[ent].frames[frame].value*curweight;
00485           curcmd.weight+=curweight;
00486           if(curweight<1)
00487             curalpha*=(1-curweight);
00488           else
00489             curalpha=0;
00490         }
00491         if(curcmd.weight>0) {
00492           
00493           sumcmd.value+=curcmd.value/curcmd.weight*alpha*(1-curalpha);
00494           sumcmd.weight+=alpha*(1-curalpha);
00495           alpha*=curalpha;
00496         }
00497       }
00498 
00499       
00500       
00501       if(sumcmd.weight>0) {
00502         sumcmd.value/=sumcmd.weight;
00503         outputs[frame][output]=sumcmd.value;
00504       } else 
00505         sumcmd.value=outputs[frame][output]=cmdSums[output];
00506       if(frame==NumFrames-1)
00507         cmds[output]=sumcmd;
00508     }
00509   }
00510   
00511   for(uint output=0; output<NumOutputs; output++)
00512     cmdSums[output]=outputs[NumFrames-1][output];
00513 
00514   for (uint frame_idx = 0; frame_idx < NumFrames; frame_idx++) {
00515     for(uint output=PIDJointOffset; output<PIDJointOffset+NumPIDJoints; output++)
00516       outputs[frame_idx][output] = (outputs[frame_idx][output] + config->motion.calibration_offset[output-PIDJointOffset])
00517         * config->motion.calibration_scale[output-PIDJointOffset];
00518   }
00519       
00520         
00521   
00522   for(uint output=PIDJointOffset; output<PIDJointOffset+NumPIDJoints; output++) {
00523     cmdstatelist_t& curstatelist=cmdstates[output];
00524     float alpha=1;
00525     float sumpid[3];
00526     for(uint i=0; i<3; i++)
00527       sumpid[i]=0;
00528     float sumweight=0;
00529     cmdstatelist_t::index_t ent=curstatelist.begin();
00530     while(ent!=curstatelist.end() && alpha>0) {
00531       float tmppid[3];
00532       for(uint i=0; i<3; i++)
00533         tmppid[i]=0;
00534       float tmpweight=0;
00535       float curp=curstatelist[ent].priority;
00536       float curalpha=1; 
00537       for(;ent!=curstatelist.end() && curstatelist[ent].priority==curp; ent=curstatelist.next(ent)) {
00538         
00539         float curweight=curstatelist[ent].pid.weight;
00540         ASSERT(curweight>=0,"negative PID weights are illegal")
00541         if(curweight<0) 
00542           curweight=0;
00543         for(uint i=0; i<3; i++)
00544           tmppid[i]+=curstatelist[ent].pid.pid[i]*curweight;
00545         tmpweight+=curweight;
00546         if(curweight<1)
00547           curalpha*=(1-curweight);
00548         else
00549           curalpha=0;
00550       }
00551       if(tmpweight>0) {
00552         
00553         for(uint i=0; i<3; i++)
00554           sumpid[i]+=tmppid[i]/tmpweight*(1-curalpha);
00555         sumweight+=(1-curalpha);
00556         alpha*=curalpha;
00557       }
00558     }
00559     if(sumweight>0) {
00560       for(uint i=0; i<3; i++)
00561         sumpid[i]/=sumweight;
00562       setPID(output,sumpid);
00563     }
00564   }
00565 
00566   func_end();
00567   
00568   
00569 }
00570 
00571 
00572 
00573 
00574 
00575 
00576 
00577 
00578 
00579 
00580 
00581 
00582 
00583 
00584 
00585 
00586 
00587 
00588 
00589 
00590 
00591 
00592 
00593 
00594 
00595 
00596 
00597 #ifdef PLATFORM_APERIOS
00598 bool
00599 MotionManager::updatePIDs(OPrimitiveID primIDs[NumOutputs]) {
00600   
00601   bool dirty=!pidchanges.empty();
00602   while(!pidchanges.empty()) {
00603     float gain[3];
00604     word shift[3];
00605     
00606     
00607     for(uint i=0; i<3; i++) {
00608       shift[i]=DefaultPIDShifts[i];
00609       gain[i]=pidchanges.front().pids[i]*(1<<(0x10-shift[i]));
00610     }
00611     
00612     
00613     
00614     
00615     
00616     
00617     
00618     
00619     
00620     
00621     
00622 
00623 
00624 
00625 
00626 
00627 
00628 
00629 
00630 
00631     
00632     
00633     
00634     
00635     
00636     
00637     OPENR::SetJointGain(primIDs[pidchanges.front().joint],(word)gain[0],(word)gain[1],(word)gain[2],shift[0],shift[1],shift[2]);
00638     for(uint i=0; i<3; i++)
00639       state->pids[pidchanges.front().joint][i]=pidchanges.front().pids[i];
00640     pidchanges.pop_front();
00641   }
00642   return dirty;
00643 }
00644 #else
00645 bool
00646 MotionManager::updatePIDs(std::vector<std::pair<unsigned int, float[3]> >& pids) {
00647   
00648   bool dirty=!pidchanges.empty();
00649   std::pair<unsigned int, float[3]> entry;
00650   while(!pidchanges.empty()) {
00651     entry.first=pidchanges.front().joint;
00652     for(uint i=0; i<3; i++)
00653       state->pids[entry.first][i] = entry.second[i] = pidchanges.front().pids[i];
00654     pids.push_back(entry);
00655     pidchanges.pop_front();
00656   }
00657   return dirty;
00658 }
00659 #endif //PLATFORM_APERIOS or PLATFORM_LOCAL
00660 
00661 #ifdef PLATFORM_APERIOS
00662 void
00663 MotionManager::receivedMsg(const ONotifyEvent& event) {
00664   
00665   func_begin();
00666   
00667   
00668   for(int x=0; x<event.NumOfData(); x++)
00669     processMsg(event.RCData(x));
00670   
00671   func_end();
00672 }
00673 #else //PLATFORM_LOCAL
00674 bool
00675 MotionManager::receivedMsg(RCRegion* msg) {
00676   try {
00677     Thread::NoCancelScope nc;
00678     MarkScope l(*motman->procLocks[getAccID()]);
00679     
00680 
00681 
00682     motman->processMsg(msg);
00683   } catch(const std::exception& ex) {
00684     if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionManagerMsg processing (MotionManager::receivedMsg)",&ex))
00685       throw;
00686   } catch(...) {
00687     if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionManagerMsg processing (MotionManager::receivedMsg)",NULL))
00688       throw;
00689   }
00690   return true;
00691 }
00692 #endif //PLATFORM_APERIOS or PLATFORM_LOCAL
00693 
00694 void
00695 MotionManager::processMsg(RCRegion * rcr) {
00696   
00697   if(rcr==NULL) {
00698     cout << "WARNING: MotionManager::processMsg was given a NULL region" << endl;
00699     return;
00700   }
00701   MotionManagerMsg * mminfo = reinterpret_cast<MotionManagerMsg*>(rcr->Base());
00702 #ifndef PLATFORM_APERIOS
00703   if(mminfo->creatorPID==ProcessID::getID())
00704     return; 
00705 #endif
00706 
00707   func_begin();
00708   const accID_t MYACCID = getAccID();
00709   
00710   MC_ID mc_id=mminfo->mc_id;
00711   switch(mminfo->type) {
00712     case MotionManagerMsg::addMotion: {
00713       if(mc_id==invalid_MC_ID) { 
00714         cout << "WARNING: MotionManager::processMsg addMotion for invalid_MC_ID motion" << endl;
00715         func_end();
00716         return;
00717       }
00718       if(cmdlist[mc_id].rcr[MYACCID]!=NULL) {
00719         cerr << "WARNING: MotionManager::processMsg addMotion for motion which was already added!" << endl;
00720       } else {
00721         
00722         cmdlist[mc_id].rcr[MYACCID]=rcr;
00723         
00724         rcr->AddReference();
00725         
00726         
00727         
00728         cmdlist[mc_id].baseaddrs[MYACCID]=static_cast<MotionCommand*>(mminfo);
00729       }
00730       if(ProcessID::getID()==ProcessID::MotionProcess && cmdlist[mc_id].lastAccessor!=(accID_t)-1) {
00731         checkoutMotion(mc_id,true);
00732         try {
00733           cmdlist[mc_id].baseaddrs[MYACCID]->start();
00734         } catch(const std::exception& ex) {
00735           ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionCommand::start()",&ex);
00736         } catch(...) {
00737           ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionCommand::start()",NULL);
00738         }
00739         checkinMotion(mc_id);
00740       }
00741     } break;
00742     case MotionManagerMsg::deleteMotion: {
00743       
00744       
00745       ASSERT(cmdlist[mc_id].lastAccessor==(accID_t)-1,"delete motion message for motion command not marked for deletion");
00746       if(cmdlist[mc_id].rcr[MYACCID]==NULL) {
00747         cout << "WARNING: MotionManager attempted to delete a NULL motion! mc_id="<<mc_id<<" process=" << ProcessID::getIDStr() << endl;
00748         stacktrace::displayCurrentStackTrace();
00749       } else {
00750         cmdlist[mc_id].lock.lock(MYACCID);
00751         unsigned int found=0;
00752         for(unsigned int i=0; i<numAcc; i++) {
00753           if(cmdlist[mc_id].rcr[i]!=NULL) {
00754             found++;
00755           }
00756         }
00757         ASSERT(found>0,"WARNING: MotionManager::processMsg underflow");
00758         if(found==1 && mc_id==cmdlist[mc_id].baseaddrs[MYACCID]->mc_id) 
00759           cmdlist[mc_id].baseaddrs[MYACCID]->clearID();
00760         cmdlist[mc_id].rcr[MYACCID]->RemoveReference();
00761         cmdlist[mc_id].rcr[MYACCID]=NULL;
00762         cmdlist[mc_id].baseaddrs[MYACCID]=NULL;
00763         if(found==1) {
00764           push_free(mc_id); 
00765         } else {
00766           cmdlist[mc_id].lock.unlock();
00767         }
00768         if(ProcessID::getID()==ProcessID::MainProcess) {
00769           try {
00770             erouter->postEvent(EventBase::motmanEGID,mc_id,EventBase::deactivateETID,0);
00771           } catch(const std::exception& ex) {
00772             ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during event posting",&ex);
00773           } catch(...) {
00774             ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during event posting",NULL);
00775           }
00776         }
00777       }
00778       
00779     } break;
00780     default:
00781       printf("*** WARNING *** unknown MotionManager msg type received\n");
00782   }
00783   
00784   func_end();
00785 }
00786 
00787 
00788 
00789 
00790 
00791 
00792 MotionManager::MC_ID 
00793 MotionManager::doAddMotion(const SharedObjectBase& sm, bool autoprune, float priority) {
00794   MotionCommand * mc = dynamic_cast<MotionCommand*>(static_cast<MotionManagerMsg*>(sm.data()));
00795   if(mc==NULL) {
00796     cout << "MotionManager::addMotion() - SharedObject does not seem to hold a MotionCommand" << endl;
00797     return invalid_MC_ID;
00798   }
00799   mc->setAutoPrune(autoprune);
00800   
00801   while(numAcc<MAX_ACCESS-1) { std::cout << "WAIT" << std::flush; } 
00802   func_begin();
00803   const accID_t MYACCID = getAccID();
00804   
00805   
00806   for(MC_ID it=cmdlist.begin(); it!=cmdlist.end(); it=cmdlist.next(it)) {
00807     if(cmdlist[it].baseaddrs[MYACCID]==mc) {
00808       cerr << "Warning: adding motion command at " << mc << ", is already running in motion manager as MC_ID " << it << endl;
00809       return func_end(it);
00810     }
00811   }
00812   MC_ID mc_id = pop_free();
00813   
00814   if(mc_id==cmdlist.end()) {
00815     cout << "MotionManager::addMotion() - Out of room, could not add" << endl;
00816     return func_end(cmdlist.end());
00817   }
00818   
00819   mc->setAdd(mc_id);
00820   cmdlist[mc_id].baseaddrs[MYACCID]=mc;
00821   cmdlist[mc_id].rcr[MYACCID]=sm.getRegion();
00822   
00823   cmdlist[mc_id].rcr[MYACCID]->AddReference();
00824   
00825   cmdlist[mc_id].lastAccessor=MYACCID;
00826   cmdlist[mc_id].priority=priority;
00827   try {
00828     erouter->postEvent(EventBase::motmanEGID,mc_id,EventBase::activateETID,0);
00829   } catch(const std::exception& ex) {
00830     ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during event posting",&ex);
00831   } catch(...) {
00832     ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during event posting",NULL);
00833   }
00834   
00835   
00836   
00837 #ifdef PLATFORM_APERIOS
00838   OStatus err;
00839   
00840 
00841 
00842 
00843 
00844 
00845 
00846   
00847   err=subjs[MYACCID]->SetData(sm.getRegion());
00848   ASSERT(err==oSUCCESS,"*** ERROR MotionManager: SetData returned " << err);
00849   
00850   err=subjs[MYACCID]->NotifyObservers();
00851   ASSERT(err==oSUCCESS,"*** ERROR MotionManager: NotifyObservers returned " << err);
00852 #else //PLATFORM_LOCAL
00853   try {
00854     subjs[MYACCID]->sendMessage(sm.getRegion());
00855   } catch(const std::exception& ex) {
00856     ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during message sending",&ex);
00857   } catch(...) {
00858     ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during message sending",NULL);
00859   }
00860 #endif //PLATFORM check for IPC stuff
00861   
00862   
00863   return func_end(mc_id);
00864 }
00865 
00866 MotionCommand *
00867 MotionManager::checkoutMotion(MC_ID mcid,bool block) const {
00868   
00869   if(mcid>=MAX_MOTIONS || mcid==invalid_MC_ID) {
00870     cout << "*** ERROR *** " << ProcessID::getIDStr() << " tried to access invalid mcid " << mcid << endl;
00871     stacktrace::displayCurrentStackTrace();
00872     return NULL;
00873   }
00874   if(cmdlist[mcid].lastAccessor==(accID_t)-1) { 
00875     cout << "*** WARNING *** " << ProcessID::getIDStr() << " tried to access dead mcid " << mcid << endl;
00876     stacktrace::displayCurrentStackTrace();
00877     return NULL;
00878   }
00879   
00880   if(block)
00881     cmdlist[mcid].lock.lock(getAccID());
00882   else
00883     if(!cmdlist[mcid].lock.try_lock(getAccID()))
00884       return NULL;
00885   if(cmdlist[mcid].lastAccessor==(accID_t)-1) { 
00886     cout << "*** WARNING *** " << ProcessID::getIDStr() << " tried to access mcid as it was removed " << mcid << endl;
00887     stacktrace::displayCurrentStackTrace();
00888     cmdlist[mcid].lock.unlock();
00889     return NULL;
00890   }
00891   
00892   
00893   return convertMotion(mcid);
00894 }
00895 
00896 MotionCommand *
00897 MotionManager::convertMotion(MC_ID mc) const {
00898   const accID_t MYACCID = getAccID();
00899   MotionCommand * base = cmdlist[mc].baseaddrs[MYACCID];
00900   
00901   if(cmdlist[mc].lastAccessor!=MYACCID) {
00902     
00903     
00904     
00905     
00906     cmdlist[mc].lastAccessor=MYACCID;
00907   }
00908   base->setTranslator(etrans);
00909 #ifdef PLATFORM_APERIOS
00910   base->setWorldState(state);
00911 #endif
00912   return base;
00913 }
00914 
00915 void
00916 MotionManager::checkinMotion(MC_ID mcid) const {
00917   if(mcid>=MAX_MOTIONS || mcid==invalid_MC_ID) {
00918     cout << "*** ERROR *** " << ProcessID::getIDStr() << " tried to checkin invalid mcid " << mcid << endl;
00919     stacktrace::displayCurrentStackTrace();
00920     return;
00921   }
00922   const accID_t MYACCID = getAccID();
00923   if(cmdlist[mcid].lock.get_lock_level()==1 && cmdlist[mcid].rcr[MYACCID]!=NULL) { 
00924     MotionCommand * base = cmdlist[mcid].baseaddrs[MYACCID];
00925     base->setTranslator(NULL);
00926 #ifdef PLATFORM_APERIOS
00927     base->setWorldState(NULL);
00928 #endif
00929   }
00930   cmdlist[mcid].lock.unlock();
00931 }
00932 
00933 void
00934 MotionManager::removeMotion(MC_ID mcid) {
00935   if(mcid>=MAX_MOTIONS || mcid==invalid_MC_ID)
00936     return;
00937   func_begin();
00938   const accID_t MYACCID = getAccID();
00939   if(cmdlist[mcid].lastAccessor==(accID_t)-1) {
00940     cout << "WARNING: removeMotion called for a motion which has already been removed mc_id="<<mcid<<" process=" << ProcessID::getIDStr() << endl;
00941     stacktrace::displayCurrentStackTrace();
00942     func_end();
00943     return;
00944   }
00945   if(cmdlist[mcid].rcr[MYACCID]==NULL) { 
00946     cout << "WARNING: removeMotion called for a NULL motion! mc_id="<<mcid<<" process=" << ProcessID::getIDStr() << endl;
00947     stacktrace::displayCurrentStackTrace();
00948     func_end();
00949     return;
00950   }
00951   cmdlist[mcid].lock.lock(MYACCID);
00952   MotionCommand * mc=checkoutMotion(mcid,true);
00953   try {
00954     mc->stop();
00955   } catch(const std::exception& ex) {
00956     ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionCommand::stop()",&ex);
00957   } catch(...) {
00958     ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MotionCommand::stop()",NULL);
00959   }
00960   checkinMotion(mcid);
00961   cmdlist[mcid].lastAccessor=(accID_t)-1;
00962   cmdlist[mcid].rcr[MYACCID]->RemoveReference();
00963   cmdlist[mcid].rcr[MYACCID]=NULL;
00964   cmdlist[mcid].baseaddrs[MYACCID]=NULL;
00965   cmdlist[mcid].lock.unlock();
00966   if(ProcessID::getID()==ProcessID::MainProcess) {
00967     try {
00968       erouter->postEvent(EventBase::motmanEGID,mcid,EventBase::deactivateETID,0);
00969     } catch(const std::exception& ex) {
00970       ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during event posting",&ex);
00971     } catch(...) {
00972       ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during event posting",NULL);
00973     }
00974   }
00975 #ifdef PLATFORM_APERIOS
00976   MotionManagerMsg dmsg;
00977   dmsg.setDelete(mcid);
00978   
00979   subjs[MYACCID]->SetData(&dmsg,sizeof(dmsg));
00980   subjs[MYACCID]->NotifyObservers();
00981 #else //PLATFORM_LOCAL
00982   
00983   SharedObject<MotionManagerMsg> dmsg;
00984   dmsg->setDelete(mcid);
00985   
00986   try {
00987     subjs[MYACCID]->sendMessage(dmsg.getRegion());
00988   } catch(const std::exception& ex) {
00989     ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during message sending",&ex);
00990   } catch(...) {
00991     ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during message sending",NULL);
00992   }
00993 #endif //PLATFORM check for IPC stuff
00994   func_end();
00995 }
00996 
00997 
00998 
00999 
01000 
01001 
01002 void
01003 MotionManager::setPID(unsigned int joint, const float pids[3]) {
01004   func_begin();
01005 
01006   
01007   for(uint u = pidchanges.begin(); u!=pidchanges.end(); u=pidchanges.next(u)) {
01008     if(pidchanges[u].joint==joint) { 
01009       for(uint i=0; i<3; i++) {
01010         pidchanges[u].pids[i]=pids[i];
01011         if(pids[i]!=state->pids[joint][i]) { 
01012           for(i++; i<3; i++) 
01013             pidchanges[u].pids[i]=pids[i];
01014           func_end();
01015           return;
01016         }
01017       }
01018       
01019       
01020       pidchanges.erase(u);
01021       func_end();
01022       return;
01023     }
01024   }
01025 
01026   
01027   for(uint i=0; i<3; i++) 
01028     if(pids[i]!=state->pids[joint][i]) {
01029       PIDUpdate update(joint,pids); 
01030       pidchanges.push_back(update);
01031       
01032       
01033       
01034       break;
01035     }
01036   func_end();
01037 }
01038 
01039 
01040 MotionManager::MC_ID
01041 MotionManager::skip_ahead(MC_ID mcid) const {
01042   
01043   
01044   while(mcid!=cmdlist.end() && cmdlist[mcid].rcr[getAccID()]==NULL)
01045     mcid=cmdlist.next(mcid);
01046   return mcid;
01047 }
01048 
01049 MotionManager::OutputState::OutputState()
01050   : priority(0),mcid(MotionManager::invalid_MC_ID), pid()
01051 {}
01052 MotionManager::OutputState::OutputState(unsigned int out, float pri, MC_ID mc, const OutputCmd cmds[NumFrames])
01053   : priority(pri),mcid(mc), pid(DefaultPIDs[out])
01054 {
01055   for(unsigned int i=0; i<NumFrames; i++)
01056     frames[i]=cmds[i];
01057 }
01058 MotionManager::OutputState::OutputState(unsigned int out, float pri, MC_ID mc, const OutputCmd& cmd)
01059   : priority(pri),mcid(mc), pid(DefaultPIDs[out])
01060 {
01061   for(unsigned int i=0; i<NumFrames; i++)
01062     frames[i]=cmd;
01063 }
01064 MotionManager::OutputState::OutputState(unsigned int out, float pri, MC_ID mc, const OutputCmd& cmd, unsigned int frame)
01065   : priority(pri),mcid(mc), pid(DefaultPIDs[out])
01066 {
01067   frames[frame]=cmd;
01068 }
01069 MotionManager::OutputState::OutputState(unsigned int , float pri, MC_ID mc, const OutputPID& p)
01070   : priority(pri),mcid(mc), pid(p)
01071 {}
01072 MotionManager::OutputState::OutputState(unsigned int , float pri, MC_ID mc, const OutputCmd cmds[NumFrames], const OutputPID& p)
01073   : priority(pri),mcid(mc), pid(p)
01074 {
01075   for(unsigned int i=0; i<NumFrames; i++)
01076     frames[i]=cmds[i];
01077 }
01078 MotionManager::OutputState::OutputState(unsigned int , float pri, MC_ID mc, const OutputCmd& cmd, const OutputPID& p)
01079   : priority(pri),mcid(mc), pid(p)
01080 {
01081   for(unsigned int i=0; i<NumFrames; i++)
01082     frames[i]=cmd;
01083 }
01084 
01085 
01086 
01087 
01088 
01089 
01090 
01091 
01092 
01093 
01094 
01095 
01096 
01097 
01098 
01099 
01100 
01101 
01102 
01103 
01104 
01105 
01106 
01107 
01108 
01109 
01110 
01111 
01112 
01113   
01114 
01115 
01116 
01117 
01118 
01119 
01120 
01121 
01122   
01123 
01124 
01125 
01126 
01127 
01128 
01129 
01130