[Fawkes Git] branch/fzwilling/robot-memory: 4 revs updated. (0.5.0-3428-g60b435c)

Frederik Zwilling zwilling at kbsg.rwth-aachen.de
Thu Oct 27 20:10:43 CEST 2016


Changes have been pushed for the project "Fawkes Robotics Software Framework".

Gitweb: http://git.fawkesrobotics.org/fawkes.git
Trac:   http://trac.fawkesrobotics.org

The branch, fzwilling/robot-memory has been updated
        to  60b435c6524e8d4411feca88d83007991ec2784e (commit)
       via  be4214aee6d19210d3449972c9b04f4f2f94d465 (commit)
       via  5c9f7492f882f64585825845aecd4adef3ec0f15 (commit)
       via  158cbdefb42524f5a575b1797f96e5478fb345fd (commit)
      from  d08ddcdd5271f7ea692462522711841cf6ca256f (commit)

http://git.fawkesrobotics.org/fawkes.git/fzwilling/robot-memory

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- *Log* ---------------------------------------------------------------
commit 158cbdefb42524f5a575b1797f96e5478fb345fd
Author:     Frederik Zwilling <zwilling at kbsg.rwth-aachen.de>
AuthorDate: Tue Oct 18 18:25:35 2016 +0200
Commit:     Frederik Zwilling <zwilling at kbsg.rwth-aachen.de>
CommitDate: Thu Oct 27 20:09:58 2016 +0200

    robot-memory: improved documentation

http://git.fawkesrobotics.org/fawkes.git/commit/158cbde
http://trac.fawkesrobotics.org/changeset/158cbde

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 5c9f7492f882f64585825845aecd4adef3ec0f15
Author:     Frederik Zwilling <zwilling at kbsg.rwth-aachen.de>
AuthorDate: Fri Oct 21 21:37:29 2016 +0200
Commit:     Frederik Zwilling <zwilling at kbsg.rwth-aachen.de>
CommitDate: Thu Oct 27 20:10:02 2016 +0200

    robot-memory: class and api skeleton for computables

http://git.fawkesrobotics.org/fawkes.git/commit/5c9f749
http://trac.fawkesrobotics.org/changeset/5c9f749

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit be4214aee6d19210d3449972c9b04f4f2f94d465
Author:     Frederik Zwilling <zwilling at kbsg.rwth-aachen.de>
AuthorDate: Thu Oct 27 19:39:23 2016 +0200
Commit:     Frederik Zwilling <zwilling at kbsg.rwth-aachen.de>
CommitDate: Thu Oct 27 20:10:06 2016 +0200

    robot-memory: registering, checking, and executing computables
    
    Computables provide information computation on demand when querying
    (e.g. for interfacing perception, and geting complex information that
    would be inpractical to store permanently in the robot memory such as
    object distances). You can register a computable in the robot memory
    by giving a function that returns a list of computed documents. The
    function receives the query that should be executed at the moment and
    which usually contains more information about what should be computed.
    When registering a computable, you also need to give an identifyer
    query that defines when to call the computable by checking if the
    current query is matched by the identifyer query.

http://git.fawkesrobotics.org/fawkes.git/commit/be4214a
http://trac.fawkesrobotics.org/changeset/be4214a

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
commit 60b435c6524e8d4411feca88d83007991ec2784e
Author:     Frederik Zwilling <zwilling at kbsg.rwth-aachen.de>
AuthorDate: Thu Oct 27 20:05:54 2016 +0200
Commit:     Frederik Zwilling <zwilling at kbsg.rwth-aachen.de>
CommitDate: Thu Oct 27 20:10:10 2016 +0200

    robot-memory: computable unit test: addition and adding multiple docs

http://git.fawkesrobotics.org/fawkes.git/commit/60b435c
http://trac.fawkesrobotics.org/changeset/60b435c

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


- *Summary* -----------------------------------------------------------
 .../clips-robot-memory/clips_rm_trigger.cpp        |    5 +-
 src/plugins/robot-memory/computable.cpp            |   84 ++++++++++++++
 .../robot-memory/{event_trigger.h => computable.h} |   37 +++----
 src/plugins/robot-memory/computables_manager.cpp   |  118 ++++++++++++++++++++
 src/plugins/robot-memory/computables_manager.h     |   73 ++++++++++++
 src/plugins/robot-memory/event_trigger_manager.h   |    9 ++-
 src/plugins/robot-memory/robot_memory.cpp          |  109 +++++++++++++++---
 src/plugins/robot-memory/robot_memory.h            |   22 +++-
 .../robot-memory/test-plugin/robot_memory_test.cpp |   56 +++++++++
 .../robot-memory/test-plugin/robot_memory_test.h   |   40 +++++++
 10 files changed, 506 insertions(+), 47 deletions(-)
 create mode 100644 src/plugins/robot-memory/computable.cpp
 copy src/plugins/robot-memory/{event_trigger.h => computable.h} (52%)
 create mode 100644 src/plugins/robot-memory/computables_manager.cpp
 create mode 100644 src/plugins/robot-memory/computables_manager.h


- *Diffs* -------------------------------------------------------------

- *commit* 158cbdefb42524f5a575b1797f96e5478fb345fd - - - - - - - - - -
Author:  Frederik Zwilling <zwilling at kbsg.rwth-aachen.de>
Date:    Tue Oct 18 18:25:35 2016 +0200
Subject: robot-memory: improved documentation

 .../clips-robot-memory/clips_rm_trigger.cpp        |    5 +-
 src/plugins/robot-memory/event_trigger_manager.h   |    9 ++-
 src/plugins/robot-memory/robot_memory.cpp          |   78 ++++++++++++++++++++
 src/plugins/robot-memory/robot_memory.h            |    3 -
 4 files changed, 88 insertions(+), 7 deletions(-)

_Diff for modified files_:
diff --git a/src/plugins/clips-robot-memory/clips_rm_trigger.cpp b/src/plugins/clips-robot-memory/clips_rm_trigger.cpp
index ad8aba5..fb635c5 100644
--- a/src/plugins/clips-robot-memory/clips_rm_trigger.cpp
+++ b/src/plugins/clips-robot-memory/clips_rm_trigger.cpp
@@ -49,6 +49,7 @@ void ClipsRmTrigger::set_trigger(EventTrigger *trigger)
 
 /**
  * Callback function for the trigger. Asserts a fact about the update with the assert_name and updated object.
+ * When you retract the fact about the update, also call bson-destroy on the included pointer to avoid memory leaks.
  * @param update updated object
  */
 void ClipsRmTrigger::callback(mongo::BSONObj update)
@@ -70,9 +71,7 @@ void ClipsRmTrigger::callback(mongo::BSONObj update)
     fact->set_slot("ptr", CLIPS::Value(ptr));
     CLIPS::Fact::pointer new_fact = clips->assert_fact(fact);
 
-    if (new_fact) {
-      //TODO: msg_facts_[new_fact->index()] = new_fact;
-    } else {
+    if (!new_fact) {
       logger->log_warn("CLIPS-RobotMemory", "Asserting robmem-trigger fact failed");
       delete static_cast<BSONObjBuilder *>(ptr);
     }
diff --git a/src/plugins/robot-memory/event_trigger_manager.h b/src/plugins/robot-memory/event_trigger_manager.h
index f25253d..6b872c5 100644
--- a/src/plugins/robot-memory/event_trigger_manager.h
+++ b/src/plugins/robot-memory/event_trigger_manager.h
@@ -45,6 +45,14 @@ class EventTriggerManager
     EventTriggerManager(fawkes::Logger* logger, fawkes::Configuration* config);
     virtual ~EventTriggerManager();
 
+    /**
+     * Register a trigger to be notified when the robot memory is updated and the updated document matches the query
+     * @param query Query the updated document has to match
+     * @param collection db.collection to use
+     * @param callback Callback function (e.g. &Class::callback)
+     * @param _obj Pointer to class the callback is a function of (usaually this)
+     * @return Trigger object pointer, save it to remove the trigger later
+     */
     template<typename T>
     EventTrigger* register_trigger(mongo::Query query, std::string collection, void(T::*callback)(mongo::BSONObj), T *obj)
     {
@@ -80,7 +88,6 @@ class EventTriggerManager
       return trigger;
     }
 
-
     void remove_trigger(EventTrigger* trigger);
 
   private:
diff --git a/src/plugins/robot-memory/robot_memory.cpp b/src/plugins/robot-memory/robot_memory.cpp
index e48d09a..9646e11 100644
--- a/src/plugins/robot-memory/robot_memory.cpp
+++ b/src/plugins/robot-memory/robot_memory.cpp
@@ -35,6 +35,23 @@
 using namespace mongo;
 using namespace fawkes;
 
+/** @class RobotMemory "robot_memory.h"
+ * Access to the robot memory based on mongodb.
+ * Using this class, you can query/insert/remove/update information in the robot memory.
+ * Furthermore, you can register trigger to get notified when something was changed in the robot memory matching your query
+ * and you can access computables, which are on demand computed information, by registering the computables
+ * and then querying as if the information would already be in the database.
+ * @author Frederik Zwilling
+ */
+
+/**
+ * Robot Memory Constructor
+ * @param config Fawkes config
+ * @param logger Fawkes logger
+ * @param clock Fawkes clock
+ * @param mongodb_client Fawkes mongo client from the mongo aspect
+ * @param blackboard Fawkes blackboard
+ */
 RobotMemory::RobotMemory(fawkes::Configuration* config, fawkes::Logger* logger,
    fawkes::Clock* clock, mongo::DBClientBase* mongodb_client,
    fawkes::BlackBoard* blackboard)
@@ -88,6 +105,12 @@ void RobotMemory::loop()
   trigger_manager_->check_events();
 }
 
+/**
+ * Query information from the robot memory.
+ * @param query The query returned documents have to match (essentially a BSONObj)
+ * @param collection The database and collection to query as string (e.g. robmem.worldmodel)
+ * @return Cursor to get the documents from, NULL for invalid query
+ */
 QResCursor RobotMemory::query(Query query, std::string collection)
 {
   check_collection_name(collection);
@@ -129,6 +152,12 @@ QResCursor RobotMemory::query(Query query, std::string collection)
   return cursor;
 }
 
+/**
+ * Inserts a document into the robot memory
+ * @param obj The document as BSONObj
+ * @param collection The database and collection to use as string (e.g. robmem.worldmodel)
+ * @return 1: Success 0: Error
+ */
 int RobotMemory::insert(BSONObj obj, std::string collection)
 {
   check_collection_name(collection);
@@ -151,11 +180,25 @@ int RobotMemory::insert(BSONObj obj, std::string collection)
   return 1;
 }
 
+/**
+ * Inserts a document into the robot memory
+ * @param obj_str The document as json string
+ * @param collection The database and collection to use as string (e.g. robmem.worldmodel)
+ * @return 1: Success 0: Error
+ */
 int RobotMemory::insert(std::string obj_str, std::string collection)
 {
   return insert(fromjson(obj_str), collection);
 }
 
+/**
+ * Updates documents in the robot memory
+ * @param query The query defining which documents to update
+ * @param update What to change in these documents
+ * @param collection The database and collection to use as string (e.g. robmem.worldmodel)
+ * @param upsert Should the update document be inserted if the query returns no documents?
+ * @return 1: Success 0: Error
+ */
 int RobotMemory::update(Query query, BSONObj update, std::string collection, bool upsert)
 {
   check_collection_name(collection);
@@ -175,11 +218,25 @@ int RobotMemory::update(Query query, BSONObj update, std::string collection, boo
   return 1;
 }
 
+/**
+ * Updates documents in the robot memory
+ * @param query The query defining which documents to update
+ * @param update_str What to change in these documents as json string
+ * @param collection The database and collection to use as string (e.g. robmem.worldmodel)
+ * @param upsert Should the update document be inserted if the query returns no documents?
+ * @return 1: Success 0: Error
+ */
 int RobotMemory::update(Query query, std::string update_str, std::string collection, bool upsert)
 {
   return update(query, fromjson(update_str), collection, upsert);
 }
 
+/**
+ * Remove documents from the robot memory
+ * @param query Which documents to remove
+ * @param collection The database and collection to use as string (e.g. robmem.worldmodel)
+ * @return 1: Success 0: Error
+ */
 int RobotMemory::remove(Query query, std::string collection)
 {
   check_collection_name(collection);
@@ -199,12 +256,21 @@ int RobotMemory::remove(Query query, std::string collection)
   return 1;
 }
 
+/**
+ * Drop (= remove) a whole collection and all documents inside it
+ * @param collection The database and collection to use as string (e.g. robmem.worldmodel)
+ * @return 1: Success 0: Error
+ */
 int RobotMemory::drop_collection(std::string collection)
 {
   log_deb("Clearing whole robot memory");
   return remove("{}", collection);
 }
 
+/**
+ * Remove the whole database of the robot memory and all documents inside
+ * @return 1: Success 0: Error
+ */
 int RobotMemory::clear_memory()
 {
   log_deb("Clearing whole robot memory");
@@ -212,6 +278,12 @@ int RobotMemory::clear_memory()
   return 1;
 }
 
+/**
+ * Restore a previously dumped collection from a directory
+ * @param collection The database and collection to use as string (e.g. robmem.worldmodel)
+ * @param directory Directory of the dump
+ * @return 1: Success 0: Error
+ */
 int RobotMemory::restore_collection(std::string collection, std::string directory)
 {
   drop_collection(collection);
@@ -258,6 +330,12 @@ int RobotMemory::restore_collection(std::string collection, std::string director
   return 1;
 }
 
+/**
+ * Dump (= save) a collection to the filesystem to restore it later
+ * @param collection The database and collection to use as string (e.g. robmem.worldmodel)
+ * @param directory Directory to dump the collection to
+ * @return 1: Success 0: Error
+ */
 int RobotMemory::dump_collection(std::string collection, std::string directory)
 {
   //resolve path to dump to
diff --git a/src/plugins/robot-memory/robot_memory.h b/src/plugins/robot-memory/robot_memory.h
index f3046b5..ac271d3 100644
--- a/src/plugins/robot-memory/robot_memory.h
+++ b/src/plugins/robot-memory/robot_memory.h
@@ -39,9 +39,6 @@ namespace fawkes {
 ///typedef for shorter type description
 typedef std::unique_ptr<mongo::DBClientCursor> QResCursor;
 
-/**
- *
- */
 class RobotMemory
 {
   friend class RobotMemoryThread;

- *commit* 5c9f7492f882f64585825845aecd4adef3ec0f15 - - - - - - - - - -
Author:  Frederik Zwilling <zwilling at kbsg.rwth-aachen.de>
Date:    Fri Oct 21 21:37:29 2016 +0200
Subject: robot-memory: class and api skeleton for computables

 .../robot-memory/computable.cpp}                   |   27 +++++---
 .../plugin.h => robot-memory/computable.h}         |   24 +++----
 ...t_memory_aspect.cpp => computables_manager.cpp} |   44 ++++++-------
 src/plugins/robot-memory/computables_manager.h     |   65 ++++++++++++++++++++
 src/plugins/robot-memory/robot_memory.cpp          |   12 +++-
 src/plugins/robot-memory/robot_memory.h            |   18 +++++-
 .../robot-memory/test-plugin/robot_memory_test.cpp |    8 +++
 .../robot-memory/test-plugin/robot_memory_test.h   |   15 +++++
 8 files changed, 164 insertions(+), 49 deletions(-)

_Diff for modified files_:
diff --git a/src/plugins/robot-memory/robot_memory.cpp b/src/plugins/robot-memory/robot_memory.cpp
index 9646e11..123028c 100644
--- a/src/plugins/robot-memory/robot_memory.cpp
+++ b/src/plugins/robot-memory/robot_memory.cpp
@@ -94,8 +94,9 @@ void RobotMemory::init()
   rm_if_->set_result("");
   rm_if_->write();
 
-  //Setup event trigger manager
+  //Setup event trigger and computables manager
   trigger_manager_ = new EventTriggerManager(logger_, config_);
+  computables_manager_ = new ComputablesManager(logger_, config_, mongodb_client_, clock_);
 
   log_deb("Initialized RobotMemory");
 }
@@ -504,3 +505,12 @@ void RobotMemory::remove_trigger(EventTrigger* trigger)
 {
   trigger_manager_->remove_trigger(trigger);
 }
+
+/**
+ * Remove previously registered computable
+ * @param computable The computable to remove
+ */
+void RobotMemory::remove_computable(Computable* computable)
+{
+  computables_manager_->remove_computable(computable);
+}
diff --git a/src/plugins/robot-memory/robot_memory.h b/src/plugins/robot-memory/robot_memory.h
index ac271d3..3c6cfe5 100644
--- a/src/plugins/robot-memory/robot_memory.h
+++ b/src/plugins/robot-memory/robot_memory.h
@@ -30,6 +30,7 @@
 #include <mongo/client/dbclient.h>
 #include "interfaces/RobotMemoryInterface.h"
 #include "event_trigger_manager.h"
+#include "computables_manager.h"
 
 namespace fawkes {
   class Mutex;
@@ -87,9 +88,23 @@ class RobotMemory
     {
       return register_trigger(mongo::fromjson(query_str), collection, callback);
     }
-
     void remove_trigger(EventTrigger* trigger);
 
+    /**
+     * Registers a Computable which provides information in the robot memory that is computed on demand.
+     *
+     * @param identifyer BSONObj describing what the function computes. Yor computable is called when an new query matches the key value fields in the identifiyer.
+     * @param compute_func Callback function that computes the information
+     * @param obj Pointer to class the callback is a function of (usaually this)
+     * @return Computable Object pointer used for removing it
+     */
+    template<typename T>
+    Computable* register_computable(mongo::BSONObj identifyer, void(T::*compute_func)(mongo::BSONObj), T *obj)
+    {
+      return computables_manager_->register_computable(identifyer, compute_func, obj);
+    }
+    void remove_computable(Computable* computable);
+
   private:
     mongo::DBClientBase* mongodb_client_;
     fawkes::Configuration* config_;
@@ -104,6 +119,7 @@ class RobotMemory
     fawkes::Mutex *mutex_;
     fawkes::RobotMemoryInterface* rm_if_;
     EventTriggerManager* trigger_manager_;
+    ComputablesManager* computables_manager_;
 
     void init();
     void loop();
diff --git a/src/plugins/robot-memory/test-plugin/robot_memory_test.cpp b/src/plugins/robot-memory/test-plugin/robot_memory_test.cpp
index 9714625..3ea632a 100644
--- a/src/plugins/robot-memory/test-plugin/robot_memory_test.cpp
+++ b/src/plugins/robot-memory/test-plugin/robot_memory_test.cpp
@@ -224,3 +224,11 @@ TEST_F(RobotMemoryTest, EventTriggerReplica)
   }
   return ::testing::AssertionSuccess();
 }
+
+
+TEST_F(RobotMemoryTest, ComputableRegisterRemove)
+{
+  TestComputable* tc = new TestComputable();
+  Computable* comp = robot_memory->register_computable(fromjson("{somekey:'value'}"), &TestComputable::compute, tc);
+  robot_memory->remove_computable(comp);
+}
diff --git a/src/plugins/robot-memory/test-plugin/robot_memory_test.h b/src/plugins/robot-memory/test-plugin/robot_memory_test.h
index 665b1c1..cd2b173 100644
--- a/src/plugins/robot-memory/test-plugin/robot_memory_test.h
+++ b/src/plugins/robot-memory/test-plugin/robot_memory_test.h
@@ -73,5 +73,20 @@ class RobotMemoryCallback
    }
 };
 
+/**
+ * Class providing a computable function
+ */
+class TestComputable
+{
+  public:
+    TestComputable()
+  {
+  };
+   ~TestComputable(){};
+   void compute(mongo::BSONObj query)
+   {
+   }
+};
+
 
 #endif

- *commit* be4214aee6d19210d3449972c9b04f4f2f94d465 - - - - - - - - - -
Author:  Frederik Zwilling <zwilling at kbsg.rwth-aachen.de>
Date:    Thu Oct 27 19:39:23 2016 +0200
Subject: robot-memory: registering, checking, and executing computables

 src/plugins/robot-memory/computable.cpp            |   49 ++++++++++++++-
 src/plugins/robot-memory/computable.h              |   14 ++++-
 src/plugins/robot-memory/computables_manager.cpp   |   67 ++++++++++++++++++++
 src/plugins/robot-memory/computables_manager.h     |   20 ++++--
 src/plugins/robot-memory/robot_memory.cpp          |   19 +-----
 src/plugins/robot-memory/robot_memory.h            |    9 ++-
 .../robot-memory/test-plugin/robot_memory_test.cpp |   13 ++++-
 .../robot-memory/test-plugin/robot_memory_test.h   |    6 ++-
 8 files changed, 167 insertions(+), 30 deletions(-)

_Diff for modified files_:
diff --git a/src/plugins/robot-memory/computable.cpp b/src/plugins/robot-memory/computable.cpp
index ddf48e5..1b9e60b 100644
--- a/src/plugins/robot-memory/computable.cpp
+++ b/src/plugins/robot-memory/computable.cpp
@@ -21,17 +21,64 @@
 
 #include "computable.h"
 
+using namespace mongo;
+
 /** @class Computable  computable.h
  * Class holding information for a single computable
  * @author Frederik Zwilling
  */
 
-Computable::Computable()
+Computable::Computable(Query query_to_compute, std::string collection, const boost::function<std::list<BSONObj> (BSONObj)> &compute_function)
 {
+  this->compute_function = compute_function;
+  this->query_to_compute = query_to_compute;
+  this->collection = collection;
 }
 
 Computable::~Computable()
 {
 }
 
+/**
+ * Compute demanded information and insert it into the robot memory
+ * @param query The query demanding the computable information
+ * @param mongodb_client Client to use to insert computed documents
+ * @return Documents to insert extended with computable meta information (e.g. caching time)
+ */
+std::list<BSONObj> Computable::compute(BSONObj query)
+{
+  // use provided function to compute demanded documents
+  std::list<BSONObj> docs = compute_function(query);
+  //add metainformation for each document
+  for(BSONObj &obj : docs)
+  {
+    BSONObjBuilder info_b;
+    info_b.append("computed", true);
+    BSONObjBuilder obj_b;
+    obj_b.appendElements(obj);
+    obj_b.append("_robmem_info", info_b.obj());
+    //override
+    obj = obj_b.obj();
+  }
+  return docs;
+}
+
+/**
+ * Gets the query that defines what information is computed by the Computable
+ * @return The query
+ */
+mongo::Query Computable::get_query()
+{
+  return query_to_compute;
+}
+
+/**
+ * Gets the collection the computable adds information to
+ * @return The query
+ */
+std::string Computable::get_collection()
+{
+  return collection;
+}
+
 
diff --git a/src/plugins/robot-memory/computable.h b/src/plugins/robot-memory/computable.h
index 41e33dd..5232b69 100644
--- a/src/plugins/robot-memory/computable.h
+++ b/src/plugins/robot-memory/computable.h
@@ -22,11 +22,23 @@
 #ifndef FAWKES_SRC_PLUGINS_ROBOT_MEMORY_COMPUTABLE_H_
 #define FAWKES_SRC_PLUGINS_ROBOT_MEMORY_COMPUTABLE_H_
 
+#include <mongo/client/dbclient.h>
+#include <boost/function.hpp>
+
 class Computable
 {
   public:
-    Computable();
+    Computable(mongo::Query query_to_compute, std::string collection, const boost::function<std::list<mongo::BSONObj> (mongo::BSONObj)> &compute_function);
     virtual ~Computable();
+
+    std::list<mongo::BSONObj> compute(mongo::BSONObj query);
+    mongo::Query get_query();
+    std::string get_collection();
+
+  private:
+    boost::function<std::list<mongo::BSONObj> (mongo::BSONObj)> compute_function;
+    mongo::Query query_to_compute;
+    std::string collection;
 };
 
 #endif /* FAWKES_SRC_PLUGINS_ROBOT_MEMORY_COMPUTABLE_H_ */
diff --git a/src/plugins/robot-memory/computables_manager.cpp b/src/plugins/robot-memory/computables_manager.cpp
index b976fe1..da8189c 100644
--- a/src/plugins/robot-memory/computables_manager.cpp
+++ b/src/plugins/robot-memory/computables_manager.cpp
@@ -20,6 +20,7 @@
  */
 
 #include "computables_manager.h"
+#include <core/exception.h>
 
 /** @class ComputablesManager  computables_manager.h
  *  This class manages registering computables and can check
@@ -27,6 +28,9 @@
  * @author Frederik Zwilling
  */
 
+using namespace fawkes;
+using namespace mongo;
+
 ComputablesManager::ComputablesManager(fawkes::Logger* logger, fawkes::Configuration* config,
   mongo::DBClientBase* mongodb_client, fawkes::Clock* clock)
 {
@@ -34,6 +38,11 @@ ComputablesManager::ComputablesManager(fawkes::Logger* logger, fawkes::Configura
   config_ = config;
   mongodb_client_ = mongodb_client;
   clock_ = clock;
+
+  matching_test_collection_ = "robmem.computables_matching";
+  try {
+    matching_test_collection_ = config_->get_string("/plugins/robot-memory/database") + ".computables_matching";
+  } catch (Exception &e) {}
 }
 
 ComputablesManager::~ComputablesManager()
@@ -47,5 +56,63 @@ ComputablesManager::~ComputablesManager()
  */
 void ComputablesManager::remove_computable(Computable* computable)
 {
+  for(std::list<Computable*>::iterator it = computables.begin(); it != computables.end(); it++)
+  {
+    if((*it) == computable)
+    {
+      Computable* comp = *it;
+      computables.erase(it);
+      delete comp;
+      return;
+    }
+  }
+}
+
+
+/**
+ * Checks if computable knowledge is queried and calls the compute functions in this case
+ * @param query The query that might ask for computable knowledge
+ * @param collection The collection that is querried
+ * @return Were computed documents added?
+ */
+bool ComputablesManager::check_and_compute(mongo::Query query, std::string collection)
+{
+  //logger_->log_info(name.c_str(), "checking query: %s", query.toString().c_str());
+  bool added_computed_docs = false;
+  //check if the query is matched by the computable identifyer
+  //to do that we just insert the query as if it would be a document and query for it with the computable identifiers
+  mongodb_client_->dropCollection(matching_test_collection_);
+  mongodb_client_->insert(matching_test_collection_, query.obj);
+  for(std::list<Computable*>::iterator it = computables.begin(); it != computables.end(); it++)
+  {
+    if(collection == (*it)->get_collection() &&  mongodb_client_->query(matching_test_collection_, (*it)->get_query())->more())
+    {
+      std::list<BSONObj> computed_docs_list = (*it)->compute(query.obj);
+      if(computed_docs_list.size() > 0)
+      {
+        //move list into vector
+        std::vector<BSONObj> computed_docs_vector{ std::make_move_iterator(std::begin(computed_docs_list)),
+          std::make_move_iterator(std::end(computed_docs_list))};
+        mongodb_client_->insert((*it)->get_collection(), computed_docs_vector);
+        added_computed_docs = true;
+      }
+    }
+  }
+  if(added_computed_docs)
+  {
+    collections_to_cleanup.push_back(collection);
+  }
+  return added_computed_docs;
+}
 
+/**
+ * Clean up all collections containing documents computed on demand
+ */
+void ComputablesManager::cleanup_computed_docs()
+{
+  for(std::string collection : collections_to_cleanup)
+  {
+    mongodb_client_->remove(collection, fromjson("{'_robmem_info.computed':true}"));
+  }
+  collections_to_cleanup.clear();
 }
diff --git a/src/plugins/robot-memory/computables_manager.h b/src/plugins/robot-memory/computables_manager.h
index a98d34b..0c3a9da 100644
--- a/src/plugins/robot-memory/computables_manager.h
+++ b/src/plugins/robot-memory/computables_manager.h
@@ -27,6 +27,8 @@
 #include <aspect/configurable.h>
 #include <aspect/clock.h>
 #include "computable.h"
+#include <boost/bind.hpp>
+#include <utility>
 
 class ComputablesManager
 {
@@ -35,21 +37,25 @@ class ComputablesManager
       mongo::DBClientBase* mongodb_client, fawkes::Clock* clock);
     virtual ~ComputablesManager();
 
-    void check_and_compute(mongo::Query query);
+    bool check_and_compute(mongo::Query query, std::string collection);
     void remove_computable(Computable* computable);
+    void cleanup_computed_docs();
 
     /**
      * Registers a Computable which provides information in the robot memory that is computed on demand.
      *
-     * @param identifyer BSONObj describing what the function computes. Yor computable is called when an new query matches the key value fields in the identifiyer.
-     * @param compute_func Callback function that computes the information
+     * @param query_to_compute Query describing what the function computes. Yor computable is called when an new query matches query_to_compute.
+     * @param collection db.collection to fill with computed information
+     * @param compute_func Callback function that computes the information and retruns a list of computed documents
      * @param obj Pointer to class the callback is a function of (usaually this)
      * @return Computable Object pointer used for removing it
      */
     template<typename T>
-    Computable* register_computable(mongo::BSONObj identifyer, void(T::*compute_func)(mongo::BSONObj), T *obj)
+    Computable* register_computable(mongo::Query query_to_compute, std::string collection, std::list<mongo::BSONObj>(T::*compute_func)(mongo::BSONObj), T *obj)
     {
-      return NULL;
+      Computable* comp = new Computable(query_to_compute, collection, boost::bind(compute_func, obj, _1));
+      computables.push_back(comp);
+      return comp;
     }
 
   private:
@@ -59,7 +65,9 @@ class ComputablesManager
     mongo::DBClientBase* mongodb_client_;
     fawkes::Clock* clock_;
 
-    std::map<mongo::BSONObj, Computable*> computables;
+    std::list<Computable*> computables;
+    std::string matching_test_collection_;
+    std::list<std::string> collections_to_cleanup;
 };
 
 #endif /* FAWKES_SRC_PLUGINS_ROBOT_MEMORY_COMPUTABLES_COMPUTABLES_MANAGER_H_ */
diff --git a/src/plugins/robot-memory/robot_memory.cpp b/src/plugins/robot-memory/robot_memory.cpp
index 123028c..bdeff5b 100644
--- a/src/plugins/robot-memory/robot_memory.cpp
+++ b/src/plugins/robot-memory/robot_memory.cpp
@@ -104,6 +104,7 @@ void RobotMemory::init()
 void RobotMemory::loop()
 {
   trigger_manager_->check_events();
+  computables_manager_->cleanup_computed_docs();
 }
 
 /**
@@ -120,22 +121,8 @@ QResCursor RobotMemory::query(Query query, std::string collection)
   //only one query at a time
   MutexLocker lock(mutex_);
 
-//  //introspect query
-//  log(query, "executing query:");
-
-//  //TODO: computation on demand
-//  //check if virtual knowledge is queried
-//  //rename field in query
-//  if(query.getFilter().hasField("class")){
-//    set_fields(query, std::string("{type:\"") +
-//               query.getFilter()["class"].String() + "\"}");
-//    remove_field(query, "class");
-//  }
-//
-//  if(query.getFilter().hasField("bbinterface")){
-//    collection = config->get_string("plugins/robot-memory/blackboard-collection");
-//    gen_blackboard_data(query.getFilter()["bbinterface"].String());
-//  }
+  //check if computation on demand is necessary and execute Computables
+  computables_manager_->check_and_compute(query, collection);
 
   //set read preference of query to nearest to read from the local replica set member first
   query.readPref(ReadPreference_Nearest, BSONArray());
diff --git a/src/plugins/robot-memory/robot_memory.h b/src/plugins/robot-memory/robot_memory.h
index 3c6cfe5..163a788 100644
--- a/src/plugins/robot-memory/robot_memory.h
+++ b/src/plugins/robot-memory/robot_memory.h
@@ -93,15 +93,16 @@ class RobotMemory
     /**
      * Registers a Computable which provides information in the robot memory that is computed on demand.
      *
-     * @param identifyer BSONObj describing what the function computes. Yor computable is called when an new query matches the key value fields in the identifiyer.
-     * @param compute_func Callback function that computes the information
+     * @param query_to_compute Query describing what the function computes. Yor computable is called when an new query matches the key value fields in the identifiyer.
+     * @param collection db.collection to fill with computed information
+     * @param compute_func Callback function that computes the information and retruns a list of computed documents
      * @param obj Pointer to class the callback is a function of (usaually this)
      * @return Computable Object pointer used for removing it
      */
     template<typename T>
-    Computable* register_computable(mongo::BSONObj identifyer, void(T::*compute_func)(mongo::BSONObj), T *obj)
+    Computable* register_computable(mongo::Query query_to_compute, std::string collection, std::list<mongo::BSONObj>(T::*compute_func)(mongo::BSONObj), T *obj)
     {
-      return computables_manager_->register_computable(identifyer, compute_func, obj);
+      return computables_manager_->register_computable(query_to_compute, collection, compute_func, obj);
     }
     void remove_computable(Computable* computable);
 
diff --git a/src/plugins/robot-memory/test-plugin/robot_memory_test.cpp b/src/plugins/robot-memory/test-plugin/robot_memory_test.cpp
index 3ea632a..c7ac7d7 100644
--- a/src/plugins/robot-memory/test-plugin/robot_memory_test.cpp
+++ b/src/plugins/robot-memory/test-plugin/robot_memory_test.cpp
@@ -229,6 +229,17 @@ TEST_F(RobotMemoryTest, EventTriggerReplica)
 TEST_F(RobotMemoryTest, ComputableRegisterRemove)
 {
   TestComputable* tc = new TestComputable();
-  Computable* comp = robot_memory->register_computable(fromjson("{somekey:'value'}"), &TestComputable::compute, tc);
+  Computable* comp = robot_memory->register_computable(fromjson("{somekey:'value'}"), "robmem.test", &TestComputable::compute, tc);
+  robot_memory->remove_computable(comp);
+}
+
+
+TEST_F(RobotMemoryTest, ComputableCall)
+{
+  TestComputable* tc = new TestComputable();
+  Computable* comp = robot_memory->register_computable(fromjson("{computed:true}"), "robmem.test", &TestComputable::compute, tc);
+  QResCursor qres = robot_memory->query(fromjson("{computed:true}"), "robmem.test");
+  ASSERT_TRUE(qres->more());
+  ASSERT_TRUE(contains_pairs(qres->next(), fromjson("{result:'this is computed'}")));
   robot_memory->remove_computable(comp);
 }
diff --git a/src/plugins/robot-memory/test-plugin/robot_memory_test.h b/src/plugins/robot-memory/test-plugin/robot_memory_test.h
index cd2b173..17a89ab 100644
--- a/src/plugins/robot-memory/test-plugin/robot_memory_test.h
+++ b/src/plugins/robot-memory/test-plugin/robot_memory_test.h
@@ -24,6 +24,7 @@
 
 #include <gtest/gtest.h>
 #include "plugins/robot-memory/robot_memory.h"
+#include <stdio.h>
 
 
 /** Environment for running Tests of the RobotMemory
@@ -83,8 +84,11 @@ class TestComputable
   {
   };
    ~TestComputable(){};
-   void compute(mongo::BSONObj query)
+   std::list<mongo::BSONObj> compute(mongo::BSONObj query)
    {
+     std::list<mongo::BSONObj> res;
+     res.push_back(mongo::fromjson("{computed:true, result:'this is computed'}"));
+     return res;
    }
 };
 

- *commit* 60b435c6524e8d4411feca88d83007991ec2784e - - - - - - - - - -
Author:  Frederik Zwilling <zwilling at kbsg.rwth-aachen.de>
Date:    Thu Oct 27 20:05:54 2016 +0200
Subject: robot-memory: computable unit test: addition and adding multiple docs

 .../robot-memory/test-plugin/robot_memory_test.cpp |   37 ++++++++++++++++++++
 .../robot-memory/test-plugin/robot_memory_test.h   |   21 +++++++++++
 2 files changed, 58 insertions(+), 0 deletions(-)

_Diff for modified files_:
diff --git a/src/plugins/robot-memory/test-plugin/robot_memory_test.cpp b/src/plugins/robot-memory/test-plugin/robot_memory_test.cpp
index c7ac7d7..cfd0e3b 100644
--- a/src/plugins/robot-memory/test-plugin/robot_memory_test.cpp
+++ b/src/plugins/robot-memory/test-plugin/robot_memory_test.cpp
@@ -243,3 +243,40 @@ TEST_F(RobotMemoryTest, ComputableCall)
   ASSERT_TRUE(contains_pairs(qres->next(), fromjson("{result:'this is computed'}")));
   robot_memory->remove_computable(comp);
 }
+
+
+TEST_F(RobotMemoryTest, ComputableCallAddition)
+{
+  TestComputable* tc = new TestComputable();
+  Computable* comp = robot_memory->register_computable(fromjson(
+      "{compute:'sum',x:{$exists:true},y:{$exists:true}}"), "robmem.test", &TestComputable::compute_sum, tc);
+  QResCursor qres = robot_memory->query(fromjson("{compute:'sum',x:15,y:4}"), "robmem.test");
+  ASSERT_TRUE(qres->more());
+  ASSERT_TRUE(contains_pairs(qres->next(), fromjson("{sum:19}")));
+  robot_memory->remove_computable(comp);
+}
+
+
+TEST_F(RobotMemoryTest, ComputableMultiple)
+{
+  TestComputable* tc = new TestComputable();
+  Computable* comp = robot_memory->register_computable(fromjson(
+      "{compute:'multiple'}"), "robmem.test", &TestComputable::compute_multiple, tc);
+  QResCursor qres = robot_memory->query(fromjson("{compute:'multiple'}"), "robmem.test");
+  std::list<int> values = {3, 2, 1};
+  ASSERT_TRUE(qres->more());
+  int got = qres->next().getField("count").Int();
+  ASSERT_TRUE(std::find(values.begin(), values.end(), got) != values.end());
+  values.remove(got);
+  ASSERT_TRUE(qres->more());
+  got = qres->next().getField("count").Int();
+  ASSERT_TRUE(std::find(values.begin(), values.end(), got) != values.end());
+  values.remove(got);
+  ASSERT_TRUE(qres->more());
+  got = qres->next().getField("count").Int();
+  ASSERT_TRUE(std::find(values.begin(), values.end(), got) != values.end());
+  values.remove(got);
+  ASSERT_EQ(0, values.size());
+  ASSERT_FALSE(qres->more());
+  robot_memory->remove_computable(comp);
+}
diff --git a/src/plugins/robot-memory/test-plugin/robot_memory_test.h b/src/plugins/robot-memory/test-plugin/robot_memory_test.h
index 17a89ab..ad596ed 100644
--- a/src/plugins/robot-memory/test-plugin/robot_memory_test.h
+++ b/src/plugins/robot-memory/test-plugin/robot_memory_test.h
@@ -84,12 +84,33 @@ class TestComputable
   {
   };
    ~TestComputable(){};
+   //Different functions for computables:
    std::list<mongo::BSONObj> compute(mongo::BSONObj query)
    {
      std::list<mongo::BSONObj> res;
      res.push_back(mongo::fromjson("{computed:true, result:'this is computed'}"));
      return res;
    }
+   std::list<mongo::BSONObj> compute_sum(mongo::BSONObj query)
+   {
+     std::list<mongo::BSONObj> res;
+     int x = query.getField("x").Int();
+     int y = query.getField("y").Int();
+     int sum = x + y;
+     mongo::BSONObjBuilder b;
+     b << "compute" << "sum" << "x" << x << "y" << y
+         << "sum" << sum;
+     res.push_back(b.obj());
+     return res;
+   }
+   std::list<mongo::BSONObj> compute_multiple(mongo::BSONObj query)
+   {
+     std::list<mongo::BSONObj> res;
+     res.push_back(mongo::fromjson("{compute:'multiple', count:1}"));
+     res.push_back(mongo::fromjson("{compute:'multiple', count:2}"));
+     res.push_back(mongo::fromjson("{compute:'multiple', count:3}"));
+     return res;
+   }
 };
 
 




-- 
Fawkes Robotics Framework                 http://www.fawkesrobotics.org


More information about the fawkes-commits mailing list