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
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
00053
00054
00055 MMlock.lock(_MMaccID);
00056
00057 subjs[_MMaccID]=subj;
00058 if(cmdlist.size()>0)
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
00073
00074
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)
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
00090
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);
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
00297
00298
00299 void
00300 MotionManager::getOutputs(float outputs[][NumOutputs]) {
00301
00302
00303 if(state==NULL) {
00304
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
00312
00313 return;
00314 }
00315 func_begin();
00316
00317
00318
00319 for(uint output=0; output<NumOutputs; output++)
00320 cmdstates[output].clear();
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
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
00338 std::list<MC_ID> unlocked;
00339 for(MC_ID it=begin(); it!=end(); it=next(it))
00340 if(cmdlist[it].lastAccessor!=(accID_t)-1)
00341 unlocked.push_back(it);
00342 unsigned int lastProcessed=get_time();
00343 while(unlocked.size()>0) {
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++;
00348 else {
00349
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);
00362
00363
00364
00365 removeMotion(*it);
00366 } else {
00367 try {
00368 mc->updateOutputs();
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);
00375 }
00376 cur_cmd=invalid_MC_ID;
00377
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
00396
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
00411
00412
00413
00414 bit=high_ent;
00415 }
00416 }
00417
00418
00419
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;
00430 for(;ent!=curstatelist.end() && curstatelist[ent].priority==curp; ent=curstatelist.next(ent)) {
00431
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)
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
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
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
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;
00478 for(;ent!=curstatelist.end() && curstatelist[ent].priority==curp; ent=curstatelist.next(ent)) {
00479
00480 float curweight=curstatelist[ent].pid.weight;
00481 ASSERT(curweight>=0,"negative PID weights are illegal")
00482 if(curweight<0)
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
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
00509
00510 }
00511
00512 void
00513 MotionManager::updateWorldState() {
00514
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
00521
00522
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
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 bool
00566 #ifdef PLATFORM_APERIOS
00567 MotionManager::updatePIDs(OPrimitiveID primIDs[NumOutputs]) {
00568 #else
00569 MotionManager::updatePIDs() {
00570 #endif
00571
00572 bool dirty=!pidchanges.empty();
00573 while(!pidchanges.empty()) {
00574 #ifdef PLATFORM_APERIOS
00575 float gain[3];
00576 word shift[3];
00577
00578
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
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
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
00622 func_begin();
00623
00624
00625 for(int x=0; x<event.NumOfData(); x++)
00626 processMsg(event.RCData(x));
00627
00628 func_end();
00629 }
00630 #else //PLATFORM_LOCAL
00631 bool
00632 MotionManager::receivedMsg(RCRegion* msg) {
00633 try {
00634 MarkScope l(*motman->procLocks[_MMaccID]);
00635
00636
00637
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
00653 if(rcr==NULL) {
00654 cout << "WARNING: MotionManager::processMsg was given a NULL region" << endl;
00655 return;
00656 }
00657 func_begin();
00658
00659 MotionManagerMsg * mminfo = reinterpret_cast<MotionManagerMsg*>(rcr->Base());
00660 MC_ID mc_id=mminfo->mc_id;
00661 if(mc_id==invalid_MC_ID) {
00662
00663 func_end();
00664 return;
00665 }
00666 switch(mminfo->type) {
00667 case MotionManagerMsg::addMotion: {
00668 if(cmdlist[mc_id].rcr[_MMaccID]==NULL) {
00669
00670 cmdlist[mc_id].rcr[_MMaccID]=rcr;
00671
00672 rcr->AddReference();
00673
00674
00675
00676 cmdlist[mc_id].baseaddrs[_MMaccID]=static_cast<MotionCommand*>(mminfo);
00677 } else {
00678 #ifdef PLATFORM_APERIOS
00679
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
00699
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
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
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;
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);
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
00749 } break;
00750 default:
00751 printf("*** WARNING *** unknown MotionManager msg type received\n");
00752 }
00753
00754 func_end();
00755 }
00756
00757
00758
00759
00760
00761
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
00771 while(numAcc<MAX_ACCESS-1) { std::cout << "WAIT" << std::flush; }
00772 func_begin();
00773
00774
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
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
00788 mc->setAdd(mc_id);
00789 cmdlist[mc_id].baseaddrs[_MMaccID]=mc;
00790 cmdlist[mc_id].rcr[_MMaccID]=sm.getRegion();
00791
00792 cmdlist[mc_id].rcr[_MMaccID]->AddReference();
00793
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
00808
00809
00810
00811
00812
00813
00814 err=subjs[_MMaccID]->SetData(sm.getRegion());
00815 ASSERT(err==oSUCCESS,"*** ERROR MotionManager: SetData returned " << err);
00816
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
00829
00830 return func_end(mc_id);
00831 }
00832
00833 MotionCommand *
00834 MotionManager::checkoutMotion(MC_ID mcid,bool block) {
00835
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
00853
00854 return convertMotion(mcid);
00855 }
00856
00857 MotionCommand *
00858 MotionManager::convertMotion(MC_ID mc) {
00859 MotionCommand * base = cmdlist[mc].baseaddrs[_MMaccID];
00860
00861 if(cmdlist[mc].lastAccessor!=_MMaccID) {
00862
00863
00864
00865
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) {
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
00936 subjs[_MMaccID]->SetData(&dmsg,sizeof(dmsg));
00937 subjs[_MMaccID]->NotifyObservers();
00938 #else //PLATFORM_LOCAL
00939
00940 SharedObject<MotionManagerMsg> dmsg;
00941 dmsg->setDelete(mcid);
00942
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
00956
00957
00958
00959 void
00960 MotionManager::setPID(unsigned int joint, const float pids[3]) {
00961 func_begin();
00962
00963
00964 for(uint u = pidchanges.begin(); u!=pidchanges.end(); u=pidchanges.next(u)) {
00965 if(pidchanges[u].joint==joint) {
00966 for(uint i=0; i<3; i++) {
00967 pidchanges[u].pids[i]=pids[i];
00968 if(pids[i]!=state->pids[joint][i]) {
00969 for(i++; i<3; i++)
00970 pidchanges[u].pids[i]=pids[i];
00971 func_end();
00972 return;
00973 }
00974 }
00975
00976
00977 pidchanges.erase(u);
00978 func_end();
00979 return;
00980 }
00981 }
00982
00983
00984 for(uint i=0; i<3; i++)
00985 if(pids[i]!=state->pids[joint][i]) {
00986 PIDUpdate update(joint,pids);
00987 pidchanges.push_back(update);
00988
00989
00990
00991 break;
00992 }
00993 func_end();
00994 }
00995
00996
00997 MotionManager::MC_ID
00998 MotionManager::skip_ahead(MC_ID mcid) const {
00999
01000
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 , float pri, MC_ID mc, const OutputPID& p)
01027 : priority(pri),mcid(mc), pid(p)
01028 {}
01029 MotionManager::OutputState::OutputState(unsigned int , 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 , 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
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093