00001 #include "WorldStatePool.h"
00002 #include "Shared/MarkScope.h"
00003 #include "Shared/debuget.h"
00004 #include "IPC/RCRegion.h"
00005 #ifndef PLATFORM_APERIOS
00006 # include "Events/EventRouter.h"
00007 # include "local/LoadFileThread.h"
00008 #endif
00009
00010
00011 using namespace std;
00012
00013 WorldStatePool::WorldStatePool() : order(), lock() {
00014
00015 while(order.size()<order.getMaxCapacity()) {
00016 unsigned int i=order.size();
00017 reading[i]=writing[i]=frames[i]=0;
00018 status[i]=0;
00019 #ifdef PLATFORM_APERIOS
00020 stateLookupMap[i]=NULL;
00021 #else
00022 complete[i]=MutexLockBase::getSemaphoreManager()->getSemaphore();
00023 #endif
00024 order.push_back(i);
00025 }
00026 #ifdef PLATFORM_APERIOS
00027 complete[order.size()-1].lock(ProcessID::getID());
00028 #else
00029 MutexLockBase::getSemaphoreManager()->setValue(complete[order.size()-1],1);
00030 #endif
00031 }
00032
00033 void WorldStatePool::doUseResource(Data& d) {
00034 Request& r=static_cast<Request&>(d);
00035 if(r.isRead) {
00036 ReadRequest& rd = static_cast<ReadRequest&>(d);
00037 if(rd.depth++==0) {
00038 rd.prev=rd.tgt;
00039 rd.bufUsed=getCurrentReadState(rd.tgt,rd.bl);
00040
00041 }
00042 } else {
00043 WriteRequest& write = static_cast<WriteRequest&>(d);
00044 if(write.depth++==0) {
00045 useResource(write.srcRequest);
00046 write.prev=write.tgt;
00047 write.bufUsed=getCurrentWriteState(write.tgt,write.frame,write.bl);
00048 if(write.bufUsed!=-1U) {
00049 write.setStatus(status[write.bufUsed]);
00050 write.setComplete(isComplete(write.bufUsed));
00051
00052 }
00053 }
00054 }
00055 #ifdef PLATFORM_APERIOS
00056 stateLookupMap[ProcessID::getID()]=state;
00057 #endif
00058 }
00059 void WorldStatePool::doReleaseResource(Data& d) {
00060 Request& r=static_cast<Request&>(d);
00061 if(r.isRead) {
00062 ReadRequest& rd = static_cast<ReadRequest&>(d);
00063 if(rd.depth==0)
00064 throw std::underflow_error("WorldStatePool read resource usage underflow");
00065 if(--rd.depth==0) {
00066 if(rd.bufUsed!=-1U) {
00067 doneReadingState(rd.bufUsed);
00068 rd.bufUsed=-1U;
00069 }
00070 rd.tgt=rd.prev;
00071 }
00072 } else {
00073 WriteRequest& write = static_cast<WriteRequest&>(d);
00074 if(write.depth==0)
00075 throw std::underflow_error("WorldStatePool write resource usage underflow");
00076 if(--write.depth==0) {
00077 if(write.bufUsed!=-1U) {
00078 status[write.bufUsed]=write.getStatus();
00079 doneWritingState(write.bufUsed,write.getComplete());
00080 write.bufUsed=-1U;
00081 }
00082 write.tgt=write.prev;
00083 releaseResource(write.srcRequest);
00084 }
00085 }
00086 #ifdef PLATFORM_APERIOS
00087 stateLookupMap[ProcessID::getID()]=state;
00088 #endif
00089 }
00090
00091 #ifdef PLATFORM_APERIOS
00092
00093 WorldStatePool::UpdateInfo* WorldStatePool::isUnread(OSensorFrameVectorData& msg, unsigned int& lastFrameNumber) {
00094
00095
00096 static UpdateInfo info;
00097 info.msg=&msg;
00098 info.frameNumber=msg.GetInfo(0)->frameNumber;
00099 unsigned int toUse=selectWriteState(info.frameNumber,true);
00100 #ifdef DEBUG
00101 info.intendedBuf=toUse;
00102 #endif
00103 if(toUse==-1U)
00104 return NULL;
00105
00106 if(frames[toUse]==info.frameNumber && isComplete(toUse)) {
00107 if(info.frameNumber-lastFrameNumber!=NumFrames)
00108 cout << ProcessID::getIDStr() << " dropped " << (info.frameNumber-lastFrameNumber-NumFrames)/NumFrames << " sensor frame(s)" << endl;
00109 lastFrameNumber=info.frameNumber;
00110
00111 return NULL;
00112 }
00113 return &info;
00114 }
00115
00116 #else //PLATFORM_LOCAL
00117
00118 WorldStatePool::UpdateInfo* WorldStatePool::isUnread(const RCRegion& msg, unsigned int curFrameNumber, unsigned int& lastFrameNumber, bool , bool ) {
00119
00120
00121 static UpdateInfo info;
00122 info.payload=LoadFileThread::deserializeHeader(msg.Base(),msg.Size(),&info.verbose,&info.frameNumber,&info.filename,&info.dataInQueue,&info.payloadSize);
00123 if(info.payload==NULL)
00124 throw std::runtime_error("deserialization of sensor update header failed");
00125 if(info.frameNumber<curFrameNumber) {
00126
00127 return NULL;
00128 }
00129 if(info.payloadSize==0)
00130 info.payload=NULL;
00131
00132 unsigned int toUse=selectWriteState(info.frameNumber,true);
00133 #ifdef DEBUG
00134 info.intendedBuf=toUse;
00135 #endif
00136 if(toUse==-1U)
00137 return NULL;
00138 if(info.verbose) {
00139 if(info.payloadSize==0)
00140 cout << ProcessID::getIDStr() << " received sensor heartbeat at " << get_time() << endl;
00141 else
00142 cout << ProcessID::getIDStr() << " received sensor data \"" << info.filename << "\" at " << get_time() << endl;
00143 }
00144
00145 if(frames[toUse]==info.frameNumber && isComplete(toUse)) {
00146 if(info.frameNumber-lastFrameNumber!=1 && info.verbose)
00147 cout << ProcessID::getIDStr() << " dropped " << (info.frameNumber-lastFrameNumber-1) << " sensor frame(s)" << endl;
00148 lastFrameNumber=info.frameNumber;
00149
00150 return NULL;
00151 }
00152 return &info;
00153 }
00154
00155 bool WorldStatePool::read(const WorldStatePool::UpdateInfo& info, WriteRequest& wsw, bool feedbackGenerated, bool zeroPIDFeedback, const PostureEngine* feedback) {
00156
00157
00158 ASSERT(feedbackGenerated || feedback==NULL, "feedbackGenerated is false, yet feedback was supplied?");
00159 if(wsw.getComplete()) {
00160
00161
00162 return true;
00163 }
00164 ASSERT((wsw.getStatus()&FEEDBACK_APPLIED)==0, "feedback applied, but apparently not completed "<<wsw.getComplete());
00165
00166
00167 if((wsw.getStatus()&SENSORS_APPLIED) != 0) {
00168
00169 if(feedback!=NULL) {
00170
00171 if(zeroPIDFeedback) {
00172
00173 for(unsigned int i=0; i<NumOutputs; i++)
00174 state->outputs[i]=feedback->getOutputCmd(i).value;
00175 } else {
00176
00177 for(unsigned int i=0; i<NumOutputs; i++)
00178 if(!isZeroPID(wsw.src,i))
00179 state->outputs[i]=feedback->getOutputCmd(i).value;
00180 }
00181 wsw.setStatus(wsw.getStatus() | FEEDBACK_APPLIED);
00182 }
00183
00184 } else {
00185
00186 static PostureEngine pose;
00187 if(info.payload==NULL) {
00188
00189
00190 pose.setLoadedSensors(wsw.src);
00191 if(!feedbackGenerated) {
00192
00193 pose.takeSnapshot(*wsw.src);
00194 pose.setWeights(1);
00195 } else if(zeroPIDFeedback) {
00196
00197 if(feedback!=NULL) {
00198 for(unsigned int i=0; i<NumPIDJoints; ++i)
00199 pose(i+PIDJointOffset)=feedback->getOutputCmd(i).value;
00200 wsw.setStatus(wsw.getStatus() | FEEDBACK_APPLIED);
00201 }
00202 } else {
00203
00204 if(feedback!=NULL) {
00205
00206 for(unsigned int i=0; i<NumPIDJoints; ++i)
00207 if(isZeroPID(wsw.src,i))
00208 pose(i+PIDJointOffset)=wsw.src->outputs[i+PIDJointOffset];
00209 else
00210 pose(i+PIDJointOffset)=feedback->getOutputCmd(i).value;
00211 wsw.setStatus(wsw.getStatus() | FEEDBACK_APPLIED);
00212 } else {
00213
00214 for(unsigned int i=0; i<NumPIDJoints; ++i)
00215 if(isZeroPID(wsw.src,i))
00216 pose(i+PIDJointOffset)=wsw.src->outputs[i+PIDJointOffset];
00217 }
00218 }
00219
00220 } else {
00221
00222 unsigned int stateFrame=state->frameNumber;
00223
00224 pose.setLoadedSensors(state);
00225
00226 if(!pose.loadBuffer(info.payload,info.payloadSize)) {
00227 cerr << "ERROR: Corrupted sensor readings received by Main" << endl;
00228 return false;
00229 }
00230 state->frameNumber=stateFrame;
00231
00232 if(stateFrame>wsw.src->frameNumber)
00233 return false;
00234 ASSERT(stateFrame<wsw.src->frameNumber || stateFrame==1 && wsw.src->frameNumber==1,"already updated (" << stateFrame << " vs " << wsw.src->frameNumber << ")? So why did " << ProcessID::getIDStr() << " parse...");
00235
00236 if(!feedbackGenerated) {
00237
00238
00239 for(unsigned int i=0; i<NumOutputs; ++i)
00240 ASSERT(pose(i).weight>0,"zero weight found after loading");
00241 } else if(zeroPIDFeedback) {
00242
00243 if(feedback!=NULL) {
00244 for(unsigned int i=0; i<NumPIDJoints; ++i)
00245 pose(i+PIDJointOffset)=feedback->getOutputCmd(i).value;
00246 wsw.setStatus(wsw.getStatus() | FEEDBACK_APPLIED);
00247 }
00248 } else {
00249
00250 if(feedback!=NULL) {
00251
00252 for(unsigned int i=0; i<NumPIDJoints; ++i)
00253 if(!isZeroPID(wsw.src,i))
00254 pose(i+PIDJointOffset)=feedback->getOutputCmd(i).value;
00255 else
00256 ASSERT(pose(i+PIDJointOffset).weight!=0,"zero weight found after loading");
00257 wsw.setStatus(wsw.getStatus() | FEEDBACK_APPLIED);
00258 } else {
00259
00260 for(unsigned int i=0; i<NumPIDJoints; ++i)
00261 if(!isZeroPID(wsw.src,i))
00262 pose(i+PIDJointOffset).weight=0;
00263 else
00264 ASSERT(pose(i+PIDJointOffset).weight!=0,"zero weight found after loading");
00265 }
00266 }
00267 }
00268 state->read(pose,wsw.src,erouter);
00269
00270 state->frameNumber=wsw.frame*4+5;
00271 wsw.setStatus(wsw.getStatus() | SENSORS_APPLIED);
00272 }
00273 wsw.setComplete(feedbackGenerated && wsw.getStatus()==(SENSORS_APPLIED|FEEDBACK_APPLIED) || !feedbackGenerated && (wsw.getStatus()&SENSORS_APPLIED)!=0);
00274
00275 return true;
00276 }
00277
00278 #endif
00279
00280
00281 unsigned int WorldStatePool::getCurrentReadState(WorldState*& tgt, bool block) {
00282 unsigned int toUse=-1U;
00283 if(block) {
00284 while(toUse!=order.end()) {
00285 {
00286 MarkScope l(lock);
00287 if(toUse!=-1U) {
00288
00289 reading[toUse]--;
00290 }
00291 toUse=order.back();
00292 reading[toUse]++;
00293 }
00294 #ifdef PLATFORM_APERIOS
00295 MarkScope wl(complete[toUse]);
00296 #else
00297 MutexLockBase::getSemaphoreManager()->testZero(complete[toUse],true);
00298 #endif
00299 }
00300 } else {
00301 MarkScope l(lock);
00302 order_t::index_t idx;
00303 for(idx=order.prev(order.end()); idx!=order.end(); idx=order.prev(idx)) {
00304 toUse=order[idx];
00305 if(isComplete(toUse))
00306 break;
00307 }
00308 if(idx==order.end()) {
00309 std::cerr << "ERROR: WorldStatePool unable to read state because none available" << std::endl;
00310 return -1U;
00311 }
00312 reading[toUse]++;
00313 }
00314
00315
00316 tgt=&states[toUse];
00317 return toUse;
00318 }
00319 void WorldStatePool::doneReadingState(unsigned int i) {
00320 MarkScope l(lock);
00321 reading[i]--;
00322
00323 }
00324
00325 bool WorldStatePool::isComplete(unsigned int idx) const {
00326 #ifdef PLATFORM_APERIOS
00327 return static_cast<unsigned int>(complete[idx].owner())==MutexLockBase::NO_OWNER;
00328 #else
00329 return MutexLockBase::getSemaphoreManager()->testZero(complete[idx],false);
00330 #endif
00331 }
00332
00333 unsigned int WorldStatePool::selectWriteState(unsigned int frame, bool block, order_t::index_t& idx) const {
00334
00335 idx=order.prev(order.end());
00336 unsigned int toUse=order[idx];
00337 if(frames[toUse]>frame) {
00338
00339
00340
00341 return -1U;
00342 }
00343 if(frames[toUse]!=frame || !block) {
00344
00345 order_t::index_t fallback=order.end();
00346 for(idx=order.begin(); idx!=order.end(); idx=order.next(idx)) {
00347 toUse=order[idx];
00348 if(frames[toUse]>=frame) {
00349 idx=order.end();
00350 break;
00351 }
00352 if(writing[toUse]==0) {
00353 if(reading[toUse]==0)
00354 break;
00355 } else if(fallback==order.end())
00356 fallback=idx;
00357 }
00358 if(idx==order.end()) {
00359 if(block && fallback!=order.end())
00360 toUse=order[idx=fallback];
00361 else {
00362 std::cerr << "ERROR: WorldStatePool unable to update state because none available" << std::endl;
00363 return -1U;
00364 }
00365 }
00366 }
00367 return toUse;
00368 }
00369
00370 unsigned int WorldStatePool::getCurrentWriteState(WorldState*& tgt, unsigned int frame, bool block) {
00371 unsigned int toUse;
00372 {
00373 MarkScope l(lock);
00374 order_t::index_t idx;
00375 toUse=selectWriteState(frame,block,idx);
00376 if(toUse==-1U)
00377 return -1U;
00378
00379
00380 writing[toUse]++;
00381 if(frames[toUse]!=frame) {
00382
00383 order.erase(idx);
00384 order.push_back(toUse);
00385 frames[toUse]=frame;
00386 status[toUse]=0;
00387 #ifdef PLATFORM_APERIOS
00388 complete[toUse].releaseAll();
00389 complete[toUse].lock(ProcessID::getID());
00390 #else
00391 MutexLockBase::getSemaphoreManager()->setValue(complete[toUse],1);
00392 #endif
00393 }
00394 }
00395 if(block) {
00396 writeLocks[toUse].lock(ProcessID::getID());
00397 } else if(!writeLocks[toUse].try_lock(ProcessID::getID())) {
00398 std::cerr << "WARNING: WorldStatePool unable to acquire write lock (blocking reader?). Trying again..." << std::endl;
00399 writeLocks[toUse].lock(ProcessID::getID());
00400 }
00401 if(toUse!=order.back()) {
00402
00403
00404
00405 doneWritingState(toUse,false);
00406 return getCurrentWriteState(tgt,frame,block);
00407 }
00408 tgt=&states[toUse];
00409 return toUse;
00410 }
00411 void WorldStatePool::doneWritingState(unsigned int i, bool completed) {
00412 MarkScope l(lock);
00413
00414 writing[i]--;
00415 if(completed) {
00416 #ifdef PLATFORM_APERIOS
00417 if(!isComplete(i))
00418 complete[i].unlock();
00419 #else
00420 MutexLockBase::getSemaphoreManager()->setValue(complete[i],0);
00421 #endif
00422 }
00423 writeLocks[i].unlock();
00424 }
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437