PluginSymbolicLog.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2013, Institute for Artificial Intelligence,
00005  *  Universität Bremen.
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/or other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of the Institute for Artificial Intelligence,
00019  *     Universität Bremen, nor the names of its contributors may be
00020  *     used to endorse or promote products derived from this software
00021  *     without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *********************************************************************/
00036 
00040 #include <plugins/symboliclog/PluginSymbolicLog.h>
00041 
00042 
00043 namespace beliefstate {
00044   namespace plugins {
00045     PLUGIN_CLASS::PLUGIN_CLASS() {
00046       this->addDependency("imagecapturer");
00047       this->setPluginVersion("0.93");
00048       
00049       m_prLastFailure = make_pair("", (Node*)NULL);
00050       
00051       // Random seed
00052       srand(time(NULL));
00053       
00054       m_ndActive = NULL;
00055     }
00056     
00057     PLUGIN_CLASS::~PLUGIN_CLASS() {
00058       for(Node* ndNode : m_lstNodes) {
00059         delete ndNode;
00060       }
00061       
00062       m_lstNodes.clear();
00063     }
00064     
00065     Result PLUGIN_CLASS::init(int argc, char** argv) {
00066       Result resInit = defaultResult();
00067       
00068       // Plan node control events
00069       this->setSubscribedToEvent("begin-context", true);
00070       this->setSubscribedToEvent("end-context", true);
00071       
00072       // Supervisor
00073       this->setSubscribedToEvent("start-new-experiment", true);
00074       
00075       // Extra information assertion
00076       this->setSubscribedToEvent("add-designator", true);
00077       this->setSubscribedToEvent("add-object", true);
00078       this->setSubscribedToEvent("add-failure", true);
00079       this->setSubscribedToEvent("catch-failure", true);
00080       this->setSubscribedToEvent("rethrow-failure", true);
00081       this->setSubscribedToEvent("add-image-from-file", true);
00082       this->setSubscribedToEvent("equate-designators", true);
00083       
00084       // Information supply services
00085       this->setOffersService("symbolic-plan-tree", true);
00086       this->setOffersService("symbolic-plan-context", true);
00087       
00088       return resInit;
00089     }
00090     
00091     Result PLUGIN_CLASS::deinit() {
00092       return defaultResult();
00093     }
00094     
00095     Result PLUGIN_CLASS::cycle() {
00096       Result resCycle = defaultResult();
00097       
00098       m_mtxEventsStore.lock();
00099       resCycle.lstEvents = m_lstEvents;
00100       m_lstEvents.clear();
00101       m_mtxEventsStore.unlock();
00102       
00103       return resCycle;
00104     }
00105     
00106     Event PLUGIN_CLASS::consumeServiceEvent(ServiceEvent seServiceEvent) {
00107       Event evReturn = defaultEvent();
00108       
00109       if(seServiceEvent.siServiceIdentifier == SI_REQUEST) {
00110         if(seServiceEvent.strServiceName == "symbolic-plan-tree") {
00111           // Requested the whole symbolic plan log
00112           evReturn.lstNodes = m_lstNodes;
00113           evReturn.lstRootNodes = m_lstRootNodes;
00114           
00115           evReturn.lstDesignatorIDs = m_lstDesignatorIDs;
00116           evReturn.lstEquations = m_lstDesignatorEquations;
00117           evReturn.lstEquationTimes = m_lstDesignatorEquationTimes;
00118         } else if(seServiceEvent.strServiceName == "symbolic-plan-context") {
00119           // Requested the current path in the symbolic plan log
00120           Node* ndCurrent = this->activeNode();
00121           
00122           while(ndCurrent) {
00123             evReturn.lstNodes.push_back(ndCurrent);
00124             evReturn.lstRootNodes = m_lstRootNodes;
00125             
00126             ndCurrent = ndCurrent->parent();
00127           }
00128         }
00129       }
00130       
00131       return evReturn;
00132     }
00133     
00134     void PLUGIN_CLASS::consumeEvent(Event evEvent) {
00135       if(evEvent.strEventName == "begin-context") {
00136         std::string strName = evEvent.cdDesignator->stringValue("_name");
00137         
00138         Node* ndFormerParent = this->relativeActiveNode(evEvent);
00139         Node* ndNew = this->addNode(strName, evEvent.nContextID, ndFormerParent);
00140         ndNew->setDescription(evEvent.cdDesignator->description());
00141         
00142         std::string strTimeStart = this->getTimeStampStr();
00143         if(evEvent.cdDesignator->childForKey("_time-start")) {
00144           strTimeStart = this->str((int)evEvent.cdDesignator->floatValue("_time-start"));
00145         }
00146         
00147         ndNew->metaInformation()->setValue(std::string("time-start"), strTimeStart);
00148         
00149         if(evEvent.cdDesignator->childForKey("_class")) {
00150           ndNew->metaInformation()->setValue(std::string("class"), evEvent.cdDesignator->stringValue("_class"));
00151           
00152           if(evEvent.cdDesignator->childForKey("_classnamespace")) {
00153             ndNew->metaInformation()->setValue(std::string("classnamespace"), evEvent.cdDesignator->stringValue("_classnamespace"));
00154           }
00155         }
00156         
00157         int nDetailLevel = (int)evEvent.cdDesignator->floatValue("_detail-level");
00158         ndNew->metaInformation()->setValue(std::string("detail-level"), nDetailLevel);
00159         
00160         Event evSymbolicBeginCtx = defaultEvent("symbolic-begin-context");
00161         evSymbolicBeginCtx.lstNodes.push_back(ndNew);
00162         this->deployEvent(evSymbolicBeginCtx);
00163         
00164         Event evSymbolicSetSubcontext = defaultEvent("symbolic-set-subcontext");
00165         evSymbolicSetSubcontext.lstNodes.push_back(ndFormerParent);
00166         evSymbolicSetSubcontext.lstNodes.push_back(ndNew);
00167         this->deployEvent(evSymbolicSetSubcontext);
00168       } else if(evEvent.strEventName == "end-context") {
00169         int nID = (int)evEvent.cdDesignator->floatValue("_id");
00170         
00171         int nSuccess = (int)evEvent.cdDesignator->floatValue("_success");
00172         Node* ndCurrent = this->relativeActiveNode(evEvent);
00173         
00174         if(ndCurrent) {
00175           if(ndCurrent->id() == nID || evEvent.cdDesignator->childForKey("_relative_context_id")) {
00176             std::stringstream sts;
00177             sts << "Received stop context designator for ID " << nID << " (success: " << (nSuccess ? "yes" : "no") << ")";
00178             this->info(sts.str());
00179             
00180             // Set success only if no failures are present (in
00181             // which case the success is set to 'false' already)
00182             if(!ndCurrent->hasFailures()) {
00183               // NOTE(winkler): This would be the right spot to
00184               // forward the 'failed' condition towards all underlying
00185               // node structures (to signal that this branch failed).
00186               ndCurrent->metaInformation()->setValue(std::string("success"), nSuccess);
00187             }
00188             
00189             std::string strTimeEnd = this->getTimeStampStr();
00190             if(evEvent.cdDesignator->childForKey("_time-end")) {
00191               strTimeEnd = this->str((int)evEvent.cdDesignator->floatValue("_time-end"));
00192             }
00193             ndCurrent->metaInformation()->setValue(std::string("time-end"), strTimeEnd);
00194             
00195             Node* ndParent = ndCurrent->parent();
00196             Node* ndParentLastValid = NULL;
00197             this->setNodeAsActive(ndParent);
00198             
00199             while(ndParent) {
00200               ndParentLastValid = ndParent;
00201               
00202               if(ndParent->prematurelyEnded()) {
00203                 std::stringstream sts_id;
00204                 sts_id << ndParent->id();
00205                 this->info("Node ID " + sts_id.str() + " ended prematurely, removing from context stack.");
00206                 
00207                 // Setting the same values for success and end time as
00208                 // for the actually ended node.
00209                 ndParent->metaInformation()->setValue(std::string("time-end"), strTimeEnd);
00210                 
00211                 // Set success only if no failures are present (in
00212                 // which case the success is set to 'false' already)
00213                 if(!ndParent->hasFailures()) {
00214                   ndParent->metaInformation()->setValue(std::string("success"), nSuccess);
00215                 }
00216                 
00217                 Event evSymbolicEndCtx = defaultEvent("symbolic-end-context");
00218                 evSymbolicEndCtx.lstNodes.push_back(ndParent);
00219                 this->deployEvent(evSymbolicEndCtx);
00220                 
00221                 ndParent = ndParent->parent();
00222               } else {
00223                 break;
00224               }
00225               
00226               this->setNodeAsActive(ndParent);
00227             }
00228             
00229             if(ndParentLastValid) {
00230               ndParentLastValid->ensureProperty("time-end", strTimeEnd);
00231             }
00232             
00233             Event evSymbolicEndCtx = defaultEvent("symbolic-end-context");
00234             evSymbolicEndCtx.lstNodes.push_back(ndCurrent);
00235             this->deployEvent(evSymbolicEndCtx);
00236           } else {
00237             std::stringstream sts;
00238             sts << "Received stop node designator for ID " << nID << " while ID " << ndCurrent->id() << " is active.";
00239             this->info(sts.str());
00240             
00241             std::string strTimeEnd = this->getTimeStampStr();
00242             Node *ndEndedPrematurely = NULL;
00243             Node *ndSearchTemp = ndCurrent;
00244             
00245             while(ndSearchTemp) {
00246               ndSearchTemp->ensureProperty("time-end", strTimeEnd);
00247               
00248               if(ndSearchTemp->id() == nID) {
00249                 ndEndedPrematurely = ndSearchTemp;
00250                 ndSearchTemp = NULL;
00251               } else {
00252                 ndSearchTemp = ndSearchTemp->parent();
00253               }
00254             }
00255             
00256             if(ndEndedPrematurely) {
00257               // Found the prematurely ended node in this branch
00258               stringstream sts;
00259               sts << "Marking node " << nID << " as prematurely ended.";
00260               this->info(sts.str());
00261               
00262               ndEndedPrematurely->setPrematurelyEnded(true);
00263             } else {
00264               // Didn't find the prematurely ended node in this branch
00265               stringstream sts;
00266               sts << "The apparently prematurely ended node " << nID << " was not found.";
00267               this->warn(sts.str());
00268             }
00269           }
00270         } else {
00271           stringstream sts;
00272           sts << "Received stop node designator for ID " << nID << " while in top-level.";
00273           this->warn(sts.str());
00274         }
00275       } else if(evEvent.strEventName == "add-image-from-file") {
00276         if(evEvent.cdDesignator) {
00277           if(this->activeNode()) {
00278             string strFilepath = evEvent.cdDesignator->stringValue("filename");
00279             string strTopic = evEvent.cdDesignator->stringValue("origin");
00280             
00281             if(strFilepath != "") {
00282               string strTimeImage = this->getTimeStampStr();
00283               
00284               Node* ndSubject = this->relativeActiveNode(evEvent);
00285               if(ndSubject) {
00286                 ndSubject->addImage(strTopic, strFilepath, strTimeImage);
00287               
00288                 this->info("Added image to active node (id " + this->str(ndSubject->id()) + "): '" + strFilepath + "'");
00289               
00290                 Event evSymbolicAddImage = defaultEvent("symbolic-add-image");
00291                 evSymbolicAddImage.lstNodes.push_back(ndSubject);
00292                 evSymbolicAddImage.cdDesignator = new CDesignator();
00293                 evSymbolicAddImage.cdDesignator->setType(ACTION);
00294                 evSymbolicAddImage.cdDesignator->setValue("origin", strTopic);
00295                 evSymbolicAddImage.cdDesignator->setValue("filename", strFilepath);
00296                 evSymbolicAddImage.cdDesignator->setValue("time-capture", strTimeImage);
00297                 evSymbolicAddImage.nOpenRequestID = evEvent.nOpenRequestID;
00298                 this->deployEvent(evSymbolicAddImage);
00299               } else {
00300                 this->fail("Cannot add image: Given relative parent node (ID = " + this->str((int)evEvent.cdDesignator->floatValue("_relative_context_id")) + ") does not exist. This is a problem.");
00301               }
00302             } else {
00303               this->warn("No filename given. Will not add unnamed image to active node. The designator was:");
00304               evEvent.cdDesignator->printDesignator();
00305             }
00306           } else {
00307             this->warn("No node context available. Cannot add image from file while on top-level.");
00308           }
00309         }
00310       } else if(evEvent.strEventName == "add-failure") {
00311         if(evEvent.cdDesignator) {
00312           Node* ndSubject = this->relativeActiveNode(evEvent);
00313           
00314           if(ndSubject) {
00315             // Adding a failure to a node also means to set its success state to 'false'.
00316             string strCondition = evEvent.cdDesignator->stringValue("condition");
00317             string strTimeFail = this->getTimeStampStr();
00318             
00319             string strFailureID = ndSubject->addFailure(strCondition, strTimeFail);
00320             this->replaceStringInPlace(strFailureID, "-", "_");
00321             
00322             m_prLastFailure = make_pair(strFailureID, ndSubject);
00323             ndSubject->setSuccess(false);
00324             
00325             this->info("Added failure '" + m_prLastFailure.first + "' to active node (id " + this->str(ndSubject->id()) + "): '" + strCondition.c_str() + "'");
00326             
00327             Event evSymbAddFailure = defaultEvent("symbolic-add-failure");
00328             evSymbAddFailure.lstNodes.push_back(ndSubject);
00329             evSymbAddFailure.cdDesignator = new CDesignator();
00330             evSymbAddFailure.cdDesignator->setType(ACTION);
00331             evSymbAddFailure.cdDesignator->setValue("condition", strCondition);
00332             evSymbAddFailure.cdDesignator->setValue("time-fail", strTimeFail);
00333             this->deployEvent(evSymbAddFailure);
00334           } else {
00335             this->warn("No node context available. Cannot add failure while on top-level (this can also mean that the targetted relative node ID does not exist).");
00336           }
00337         }
00338       } else if(evEvent.strEventName == "catch-failure") {
00339         if(evEvent.cdDesignator) {
00340           Node* ndSubject = this->relativeActiveNode(evEvent);
00341           
00342           if(ndSubject) {
00343             if(m_prLastFailure.first != "") {
00344               string strID = evEvent.cdDesignator->stringValue("context-id");
00345               
00346               if(strID != "") {
00347                 int nID;
00348                 sscanf(strID.c_str(), "%d", &nID);
00349                 
00350                 Node* ndRelative = ndSubject->relativeWithID(nID);
00351                 if(ndRelative) {
00352                   ndRelative->catchFailure(m_prLastFailure.first, m_prLastFailure.second, this->getTimeStampStr());
00353                   
00354                   // Associate this failure with its catching node
00355                   m_mapFailureCatchers[m_prLastFailure.first] = ndRelative;
00356                   
00357                   this->info("Context (ID = " + strID + ") caught failure '" + m_prLastFailure.first + "'");
00358                 } else {
00359                   this->fail("Relative with ID " + strID + " not found up the chain while catching failure.");
00360                 }
00361               } else {
00362                 this->warn("Invalid context ID when catching failure: '" + strID + "'.");
00363               }
00364             } else {
00365               this->warn("Tried to catch failure without one being present.");
00366             }
00367           } else {
00368             this->fail("Cannot catch failures outside of context.");
00369           }
00370         }
00371       } else if(evEvent.strEventName == "rethrow-failure") {
00372         if(evEvent.cdDesignator) {
00373           if(m_prLastFailure.first != "") {
00374             if(m_mapFailureCatchers[m_prLastFailure.first]) {
00375               m_mapFailureCatchers[m_prLastFailure.first]->removeCaughtFailure(m_prLastFailure.first);
00376               m_mapFailureCatchers[m_prLastFailure.first] = NULL;
00377               
00378               string strID = evEvent.cdDesignator->stringValue("context-id");
00379               this->info("Context (ID = " + strID + ") rethrew failure '" + m_prLastFailure.first + "'");
00380             } else {
00381               this->warn("Apparently caught failure '" + m_prLastFailure.first + "' is not in failure catchers map.");
00382             }
00383           } else {
00384             this->warn("Tried to rethrow failure without active failure. This is probably not what you wanted.");
00385           }
00386         }
00387       } else if(evEvent.strEventName == "add-designator") {
00388         if(evEvent.cdDesignator) {
00389           Node* ndSubject = this->relativeActiveNode(evEvent);
00390           
00391           if(ndSubject) {
00392             string strType = evEvent.cdDesignator->stringValue("type");
00393             string strAnnotation = evEvent.cdDesignator->stringValue("annotation");
00394             string strMemAddr = evEvent.cdDesignator->stringValue("memory-address");
00395             
00396             CKeyValuePair* ckvpDesc = evEvent.cdDesignator->childForKey("description");
00397             
00398             list<CKeyValuePair*> lstDescription = ckvpDesc->children();
00399             this->ensureDesignatorPublished(lstDescription, strMemAddr, strType, strAnnotation, true, this->relativeActiveNode(evEvent));
00400           } else {
00401             this->warn("No node context available. Cannot add designator while on top-level.");
00402           }
00403         }
00404       } else if(evEvent.strEventName == "equate-designators") {
00405         if(evEvent.cdDesignator) {
00406           string strMemAddrChild = evEvent.cdDesignator->stringValue("memory-address-child");
00407           string strMemAddrParent = evEvent.cdDesignator->stringValue("memory-address-parent");
00408           
00409           if(strMemAddrChild != "" && strMemAddrParent != "") {
00410             Node* ndSubject = this->relativeActiveNode(evEvent);
00411             
00412             if(ndSubject) {
00413               // Check if child designator exists
00414               CKeyValuePair* ckvpDescChild = evEvent.cdDesignator->childForKey("description-child");
00415               
00416               if(this->ensureDesignatorPublished(ckvpDescChild->children(), strMemAddrParent, evEvent.cdDesignator->stringValue("type-child"), "", false, this->relativeActiveNode(evEvent))) {
00417                 this->info("Added non-existant child-designator during 'equate'");
00418               }
00419               
00420               // Check if parent designator exists
00421               CKeyValuePair* ckvpDescParent = evEvent.cdDesignator->childForKey("description-parent");
00422               if(this->ensureDesignatorPublished(ckvpDescParent->children(), strMemAddrParent, evEvent.cdDesignator->stringValue("type-parent"), "", false, this->relativeActiveNode(evEvent))) {
00423                 this->warn("Added non-existant parent-designator during 'equate'");
00424               }
00425               
00426               CDesignator* desigChild = this->makeDesignator(evEvent.cdDesignator->stringValue("type-child"), ckvpDescChild->children());
00427               CDesignator* desigParent = this->makeDesignator(evEvent.cdDesignator->stringValue("type-parent"), ckvpDescParent->children());
00428               
00429               string strEquationTime = this->equateDesignators(strMemAddrChild, desigChild, strMemAddrParent, desigParent);
00430               
00431               delete desigChild;
00432               delete desigParent;
00433               
00434               string strUniqueIDParent = this->getDesignatorID(strMemAddrParent);
00435               string strUniqueIDChild = this->getDesignatorID(strMemAddrChild);
00436               
00437               this->info("Equated designators " + strUniqueIDChild + " (successor) and " + strUniqueIDParent + " (parent).");
00438               
00439               Event evEquateDesigs = defaultEvent("symbolic-equate-designators");
00440               evEquateDesigs.cdDesignator = new CDesignator();
00441               evEquateDesigs.cdDesignator->setType(ACTION);
00442               evEquateDesigs.cdDesignator->setValue("parent-id", strUniqueIDParent);
00443               evEquateDesigs.cdDesignator->setValue("child-id", strUniqueIDChild);
00444               evEquateDesigs.cdDesignator->setValue("equation-time", strEquationTime);
00445               
00446               this->deployEvent(evEquateDesigs);
00447             }
00448           }
00449         }
00450       } else if(evEvent.strEventName == "add-object") {
00451         if(evEvent.cdDesignator) {
00452           CKeyValuePair* ckvpDesc = evEvent.cdDesignator->childForKey("description");
00453           
00454           if(ckvpDesc) {
00455             Node* ndSubject = this->relativeActiveNode(evEvent);
00456             
00457             if(ndSubject) {
00458               string strType = evEvent.cdDesignator->stringValue("type");
00459               string strMemAddr = evEvent.cdDesignator->stringValue("memory-address");
00460               
00461               bool bDesigExists = (this->getDesignatorID(strMemAddr) != "");
00462               
00463               CDesignator* desigCurrent = this->makeDesignator(strType, ckvpDesc->children());
00464               string strUniqueID = this->getUniqueDesignatorID(strMemAddr, desigCurrent);
00465               delete desigCurrent;
00466               
00467               if(!bDesigExists) { // Object does not yet exist. Add it symbolically.
00468                 this->info("Adding non-existant object-designator to current context");
00469                 
00470                 CKeyValuePair *ckvpDesc = evEvent.cdDesignator->childForKey("description");
00471                 list<CKeyValuePair*> lstDescription = ckvpDesc->children();
00472                 
00473                 CDesignator* cdTemp = new CDesignator(OBJECT, lstDescription);
00474                 cdTemp->setValue("_id", strUniqueID);
00475                 
00476                 // First, symbolically create the designator
00477                 Event evLoggedDesignator = defaultEvent("symbolic-create-designator");
00478                 evLoggedDesignator.cdDesignator = cdTemp;
00479                 
00480                 this->deployEvent(evLoggedDesignator);
00481                 
00482                 // Second, symbolically add it to the current event
00483                 Event evAddedDesignator = defaultEvent("symbolic-add-designator");
00484                 evAddedDesignator.cdDesignator = new CDesignator(cdTemp);
00485                 evAddedDesignator.lstNodes.push_back(ndSubject);
00486                 evAddedDesignator.strAnnotation = evEvent.cdDesignator->stringValue("annotation");
00487                 
00488                 this->deployEvent(evAddedDesignator);
00489               }
00490               
00491               ckvpDesc->setValue("__id", strUniqueID);
00492               
00493               if(evEvent.cdDesignator->childForKey("class")) {
00494                 ckvpDesc->setValue(std::string("_class"), evEvent.cdDesignator->stringValue("class"));
00495                 
00496                 if(evEvent.cdDesignator->childForKey("classnamespace")) {
00497                   ckvpDesc->setValue(std::string("_classnamespace"), evEvent.cdDesignator->stringValue("classnamespace"));
00498                 }
00499               }
00500               
00501               if(evEvent.cdDesignator->childForKey("property")) {
00502                 ckvpDesc->setValue(std::string("_property"), evEvent.cdDesignator->stringValue("property"));
00503               }
00504               
00505               ndSubject->addObject(ckvpDesc->children());
00506               this->info("Added object (" + strUniqueID + ") to active node (id " + this->str(ndSubject->id()) + ").");
00507               
00508               // Signal symbolic addition of object
00509               Event evSymAddObj = defaultEvent("symbolic-add-object");
00510               evSymAddObj.cdDesignator = new CDesignator(OBJECT, ckvpDesc);
00511               
00512               // TODO(winkler): Okay, this is pretty hacky. Right now,
00513               // the CRAM system does not send object names. That
00514               // needs to be fixed. Until then, a dummy name is used
00515               // here.
00516               evSymAddObj.cdDesignator->setValue("name", "object0");//strUniqueID);
00517               
00518               if(evSymAddObj.cdDesignator->childForKey("pose") != NULL) {
00519                 if(evSymAddObj.cdDesignator->childForKey("pose")->type() == POSESTAMPED) {
00520                   evSymAddObj.cdDesignator->setValue("pose-stamped", evSymAddObj.cdDesignator->poseStampedValue("pose"));
00521                 } else if(evSymAddObj.cdDesignator->childForKey("pose")->type() == POSE) {
00522                   evSymAddObj.cdDesignator->setValue("pose", evSymAddObj.cdDesignator->poseStampedValue("pose"));
00523                 }
00524               }
00525               
00526               string strObjName = evSymAddObj.cdDesignator->stringValue("name");
00527               
00528               CKeyValuePair* ckvpMenu = evSymAddObj.cdDesignator->addChild("menu");
00529               CKeyValuePair* ckvpMenuPickObject = ckvpMenu->addChild("PICK-OBJECT");
00530               ckvpMenuPickObject->setValue("label", "Pick up object " + strObjName);
00531               ckvpMenuPickObject->setValue("parameter", strObjName);
00532               
00533               this->deployEvent(evSymAddObj);
00534             } else {
00535               this->warn("No node context available. Cannot add object while on top-level.");
00536             }
00537           }
00538         }
00539       } else if(evEvent.strEventName == "start-new-experiment") {
00540         this->info("Clearing symbolic log for new experiment.");
00541         
00542         m_mapNodeIDs.clear();
00543         
00544         for(Node* ndNode : m_lstNodes) {
00545           delete ndNode;
00546         }
00547         
00548         m_lstNodes.clear();
00549         m_lstRootNodes.clear();
00550         m_ndActive = NULL;
00551         
00552         m_lstDesignatorIDs.clear();
00553         m_lstDesignatorEquations.clear();
00554         m_lstDesignatorEquationTimes.clear();
00555         
00556         m_prLastFailure = make_pair("", (Node*)NULL);
00557         
00558         srand(time(NULL));
00559         
00560         this->info("Ready for new experiment.");
00561       } else {
00562         this->warn("Unknown event name: '" + evEvent.strEventName + "'");
00563       }
00564     }
00565     
00566     Node* PLUGIN_CLASS::addNode(string strName, int nContextID, Node* ndParent) {
00567       Node* ndNew = new Node(strName);
00568       ndNew->setID(nContextID);
00569       
00570       m_mapNodeIDs[nContextID] = ndNew;
00571       
00572       if(ndParent == NULL) {
00573         // No parent mode was manually set. Use the currently active
00574         // one.
00575         ndParent = m_ndActive;
00576       }
00577       
00578       bool bSetAsActive = (ndParent == m_ndActive);
00579       
00580       if(ndParent == NULL) {
00581         // Add a new top-level node
00582         m_lstNodes.push_back(ndNew);
00583         
00584         this->info("Adding new top-level context with ID " + this->str(nContextID));
00585       } else {
00586         // Add it as a subnode to the current contextual node
00587         ndParent->addSubnode(ndNew);
00588         
00589         this->info("Adding new sub context with ID " + this->str(nContextID));
00590       }
00591       
00592       if(bSetAsActive) {
00593         this->setNodeAsActive(ndNew);
00594         this->info("The new context's name is '" + strName + "' (now active)");
00595       } else {
00596         this->info("The new context's name is '" + strName + "'");
00597       }
00598       
00599       return ndNew;
00600     }
00601     
00602     void PLUGIN_CLASS::setNodeAsActive(Node* ndActive) {
00603       bool bSame = false;
00604       
00605       if(!m_ndActive && ndActive) {
00606         m_lstRootNodes.push_back(ndActive);
00607       }
00608       
00609       m_ndActive = ndActive;
00610       
00611       if(m_ndActive) {
00612         bSame = (m_ndActive->id() == ndActive->id());
00613       }
00614       
00615       if(m_ndActive) {
00616         if(!bSame) {
00617           this->info("Setting context ID " + this->str(m_ndActive->id()) + " as active context");         
00618         }
00619         
00620         // This activates the given node
00621         Event evActiveNode = defaultEvent("symbolic-node-active");
00622         evActiveNode.lstNodes.push_back(m_ndActive);
00623         this->deployEvent(evActiveNode);
00624       } else {
00625         this->info("Removed active context, returning to top-level");
00626         
00627         // This resets the active node (i.e. no nodes active)
00628         Event evActiveNode = defaultEvent("symbolic-node-active");
00629         this->deployEvent(evActiveNode);
00630       }
00631     }
00632     
00633     Node* PLUGIN_CLASS::activeNode() {
00634       return m_ndActive;
00635     }
00636     
00637     std::string PLUGIN_CLASS::getDesignatorID(std::string strMemoryAddress) {
00638       std::string strID = "";
00639       
00640       for(pair<string, string> prPair : m_lstDesignatorIDs) {
00641         if(prPair.first == strMemoryAddress) {
00642           strID = prPair.second;
00643           break;
00644         }
00645       }
00646       
00647       return strID;
00648     }
00649     
00650     std::string PLUGIN_CLASS::getDesignatorIDType(CDesignator* desigCurrent) {
00651       // Specialize the designator ID type here. For now, just
00652       // distinguish between action, object, and location designators.
00653       std::string strType = "designator";
00654       
00655       switch(desigCurrent->type()) {
00656       case ACTION:
00657         strType = "action";
00658         break;
00659         
00660       case OBJECT:
00661         strType = "object";
00662         break;
00663         
00664       case LOCATION:
00665         strType = "location";
00666         break;
00667         
00668       default:
00669         break;
00670       }
00671       
00672       return strType;
00673     }
00674     
00675     std::string PLUGIN_CLASS::getUniqueDesignatorID(string strMemoryAddress, CDesignator* desigCurrent) {
00676       string strID = this->getDesignatorID(strMemoryAddress);
00677       
00678       if(strID == "") {
00679         strID = this->generateRandomIdentifier(this->getDesignatorIDType(desigCurrent) + "_", 14);
00680         m_lstDesignatorIDs.push_back(make_pair(strMemoryAddress, strID));
00681       }
00682       
00683       return strID;
00684     }
00685     
00686     string PLUGIN_CLASS::generateRandomIdentifier(string strPrefix, unsigned int unLength) {
00687       stringstream sts;
00688       sts << strPrefix;
00689       
00690       for(unsigned int unI = 0; unI < unLength; unI++) {
00691         int nRandom;
00692         do {
00693           nRandom = rand() % 122 + 48;
00694         } while(nRandom < 48 ||
00695                 (nRandom > 57 && nRandom < 65) ||
00696                 (nRandom > 90 && nRandom < 97) ||
00697                 nRandom > 122);
00698         
00699         char cRandom = (char)nRandom;
00700         sts << cRandom;
00701       }
00702       
00703       return sts.str();
00704     }
00705     
00706     string PLUGIN_CLASS::equateDesignators(std::string strMAChild, CDesignator* desigChild, std::string strMAParent, CDesignator* desigParent) {
00707       string strIDChild = this->getUniqueDesignatorID(strMAChild, desigChild);
00708       string strIDParent = this->getUniqueDesignatorID(strMAParent, desigParent);
00709       
00710       string strTimeStart = this->getTimeStampStr();
00711       
00712       m_lstDesignatorEquations.push_back(make_pair(strIDParent, strIDChild));
00713       m_lstDesignatorEquationTimes.push_back(make_pair(strIDChild, strTimeStart));
00714       
00715       return strTimeStart;
00716     }
00717     
00718     bool PLUGIN_CLASS::ensureDesignatorPublished(list<CKeyValuePair*> lstDescription, string strMemoryAddress, string strType, string strAnnotation, bool bAdd, Node* ndRelative) {
00719       bool bDesigExists = (this->getDesignatorID(strMemoryAddress) != "");
00720       bool bReturn = false;
00721       bool bDeleteMe = true;
00722       
00723       if(ndRelative == NULL) {
00724         ndRelative = this->activeNode();
00725       }
00726       
00727       CDesignator* desigCurrent = this->makeDesignator(strType, lstDescription);
00728       desigCurrent->setValue("_time_created", this->getTimeStampStr());
00729       
00730       std::string strUniqueID = this->getUniqueDesignatorID(strMemoryAddress, desigCurrent);
00731       
00732       if(bAdd) {
00733         ndRelative->addDesignator(strType, desigCurrent->children(), strUniqueID, strAnnotation);
00734         
00735         this->info("Added '" + strType + "' designator (addr=" + strMemoryAddress + ") to context (id " + this->str(ndRelative->id()) + "): '" + strUniqueID + "', annotation: '" + strAnnotation + "'");
00736       }
00737       
00738       if(!bDesigExists) {
00739         desigCurrent->setValue("_id", strUniqueID);
00740         
00741         if(strAnnotation != "") {
00742           desigCurrent->setValue("_annotation", strAnnotation);
00743         }
00744         
00745         // First, symbolically create the designator
00746         Event evLoggedDesignator = defaultEvent("symbolic-create-designator");
00747         evLoggedDesignator.cdDesignator = new CDesignator(desigCurrent);
00748         evLoggedDesignator.strAnnotation = strAnnotation;
00749         
00750         this->deployEvent(evLoggedDesignator);
00751         
00752         // Second, symbolically add it to the current event
00753         Event evAddedDesignator = defaultEvent("symbolic-add-designator");
00754         evAddedDesignator.cdDesignator = new CDesignator(desigCurrent);
00755         evAddedDesignator.strAnnotation = strAnnotation;
00756         evAddedDesignator.lstNodes.push_back(ndRelative);
00757         
00758         this->deployEvent(evAddedDesignator);
00759         
00760         // Thirdly, recurse through possibly nested designators,
00761         // looking for a ''_designator_memory_address'' field being
00762         // set.
00763         this->setNestedDesignatorUniqueIDs(desigCurrent);
00764         
00765         bReturn = true;
00766       }
00767       
00768       if(bDeleteMe) {
00769         delete desigCurrent;
00770       }
00771       
00772       return bReturn;
00773     }
00774     
00775     void PLUGIN_CLASS::setNestedDesignatorUniqueIDs(CKeyValuePair* ckvpParent) {
00776       bool bIsDesignator = false;
00777       string strMemAddr = "";
00778       
00779       if(ckvpParent->childForKey("_designator_memory_address")) {
00780         strMemAddr = ckvpParent->childForKey("_designator_memory_address")->stringValue();
00781         CDesignator* desigCurrent = this->makeDesignator("", ckvpParent->children());
00782         string strID = this->getUniqueDesignatorID(strMemAddr, desigCurrent);
00783         delete desigCurrent;
00784         
00785         ckvpParent->setValue("_id", strID);
00786         bIsDesignator = true;
00787       }
00788       
00789       list<CKeyValuePair*> lstChildren = ckvpParent->children();
00790       
00791       for(CKeyValuePair* ckvpChild : lstChildren) {
00792         this->setNestedDesignatorUniqueIDs(ckvpChild);
00793       }
00794       
00795       if(bIsDesignator) {
00796         string strTypePre = ckvpParent->stringValue("_designator_type");
00797         string strType = (strTypePre == "" ? "OBJECT" : strTypePre);
00798         
00799         this->ensureDesignatorPublished(ckvpParent->children(), strMemAddr, strType);
00800       }
00801     }
00802     
00803     CDesignator* PLUGIN_CLASS::makeDesignator(enum DesignatorType edtType, list<CKeyValuePair*> lstDescription) {
00804       return new CDesignator(edtType, lstDescription);
00805     }
00806     
00807     CDesignator* PLUGIN_CLASS::makeDesignator(std::string strType, list<CKeyValuePair*> lstDescription) {
00808       enum DesignatorType edtType = UNKNOWN;
00809       
00810       if(strType == "ACTION") {
00811         edtType = ACTION;
00812       } else if(strType == "OBJECT") {
00813         edtType = OBJECT;
00814       } else if(strType == "LOCATION") {
00815         edtType = LOCATION;
00816       }
00817       
00818       return this->makeDesignator(edtType, lstDescription);
00819     }
00820     
00821     Node* PLUGIN_CLASS::nodeByID(int nID) {
00822       if(m_mapNodeIDs.find(nID) != m_mapNodeIDs.end()) {
00823         return m_mapNodeIDs[nID];
00824       }
00825       
00826       return NULL;
00827     }
00828     
00829     Node* PLUGIN_CLASS::relativeActiveNode(Event evEvent) {
00830       Node* ndSubject = this->activeNode();
00831       
00832       if(evEvent.cdDesignator) {
00833         if(evEvent.cdDesignator->childForKey("_relative_context_id")) {
00834           ndSubject = this->nodeByID(evEvent.cdDesignator->floatValue("_relative_context_id"));
00835         }
00836       }
00837       
00838       return ndSubject;
00839     }
00840   }
00841   
00842   extern "C" plugins::PLUGIN_CLASS* createInstance() {
00843     return new plugins::PLUGIN_CLASS();
00844   }
00845   
00846   extern "C" void destroyInstance(plugins::PLUGIN_CLASS* icDestroy) {
00847     delete icDestroy;
00848   }
00849 }


beliefstate
Author(s): Jan Winkler
autogenerated on Sun Oct 5 2014 22:30:15