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