diff --git a/knowrob_connector/CMakeLists.txt b/knowrob_connector/CMakeLists.txt index 6f5f647..969e305 100644 --- a/knowrob_connector/CMakeLists.txt +++ b/knowrob_connector/CMakeLists.txt @@ -5,69 +5,26 @@ project(KnowRobConnector) set(KNOWROB_CONNECTOR knowrob_connector) set(CMAKE_CXX_STANDARD 17) -# Construct Boost Python component name based on Python version -set(Boost_Python_VERSION "python${Python_VERSION_MAJOR}${Python_VERSION_MINOR}") -set(Boost_Python_COMPONENT "Boost::${Boost_Python_VERSION}") -message(STATUS "Using Boost Python component: ${Boost_Python_COMPONENT}") - -# Set Boost configurations -set(Boost_USE_STATIC_LIBS OFF) # Use shared libraries by default -set(Boost_USE_MULTITHREADED ON) -set(Boost_USE_STATIC_RUNTIME OFF) - -# Find Boost and Boost.Python -find_package(Boost 1.50 REQUIRED COMPONENTS program_options serialization ${Boost_Python_VERSION}) -if(NOT Boost_FOUND) - message(FATAL_ERROR "Boost not found!") -endif() - -# Explicitly set Boost.Python library path if necessary -set(Boost_PYTHON_LIBRARY /usr/lib/x86_64-linux-gnu/libboost_python38.so) -message(STATUS "Boost Python Library: ${Boost_PYTHON_LIBRARY}") - -INCLUDE(FindPkgConfig) - -pkg_check_modules(SWIPL REQUIRED swipl) -pkg_check_modules(MONGOC REQUIRED libmongoc-1.0) -pkg_check_modules(RAPTOR REQUIRED raptor2) -pkg_check_modules(REDLAND REQUIRED redland) -find_package(Python COMPONENTS Interpreter Development) -find_package(spdlog REQUIRED) - -set(KNOWROB_LIBRARIES - ${SWIPL_LIBRARIES} - ${MONGOC_LIBRARIES} - ${RAPTOR_LIBRARIES} - ${REDLAND_LIBRARIES} - ${Python_LIBRARIES} - spdlog::spdlog) - function(build_knowrob_connector) add_library(${KNOWROB_CONNECTOR} SHARED ${CMAKE_CURRENT_SOURCE_DIR}/src/knowrob_connector.cpp) - target_include_directories(${KNOWROB_CONNECTOR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/multiverse_client/include ${CMAKE_CURRENT_SOURCE_DIR}/knowrob/include - ${CMAKE_CURRENT_SOURCE_DIR}/knowrob/src/integration/python - ${SWIPL_INCLUDE_DIRS} - ${MONGOC_INCLUDE_DIRS} - ${RAPTOR_INCLUDE_DIRS} - ${REDLAND_INCLUDE_DIRS} - ${Python_INCLUDE_DIRS} - ${EIGEN3_INCLUDE_DIR} - ${Boost_INCLUDE_DIRS}) + ) + target_link_directories(${KNOWROB_CONNECTOR} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/multiverse_client/include + ${CMAKE_CURRENT_SOURCE_DIR}/knowrob/include + ) - if (UNIX) + if(UNIX) target_link_libraries(${KNOWROB_CONNECTOR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/lib/libmultiverse_client_json.so ${CMAKE_CURRENT_SOURCE_DIR}/lib/libknowrob.so - ${Boost_LIBRARIES} # Ensure all Boost libraries are linked - ${Boost_PYTHON_LIBRARY}) # Explicitly link Boost.Python - - install(TARGETS ${KNOWROB_CONNECTOR} DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/lib) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libknowrob_connector.so DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/lib RENAME knowrob.so) - elseif (WIN32) - # Windows-specific linking (if needed) + ) + install(TARGETS ${KNOWROB_CONNECTOR} DESTINATION + ${CMAKE_CURRENT_SOURCE_DIR}/lib + ) + elseif(WIN32) # target_link_libraries(${MULTIVERSE_CLIENT_JSON} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/lib/libmultiverse_client_json.dll) # install(TARGETS ${MULTIVERSE_CLIENT_JSON} DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/lib) endif() diff --git a/knowrob_connector/README.md b/knowrob_connector/README.md index 1219993..8203fda 100644 --- a/knowrob_connector/README.md +++ b/knowrob_connector/README.md @@ -5,10 +5,5 @@ To run this package in Python run ```bash -> python3 -Python 3.8.10 (default, Mar 11 2025, 17:45:31) -[GCC 9.4.0] on linux -Type "help", "copyright", "credits" or "license" for more information. ->>> from knowrob import * ->>> +> python3 scripts/multiverse_reasoner_test.py ``` diff --git a/knowrob_connector/dist-packages/knowrob.so b/knowrob_connector/dist-packages/knowrob.so new file mode 100755 index 0000000..35411b6 Binary files /dev/null and b/knowrob_connector/dist-packages/knowrob.so differ diff --git a/knowrob_connector/lib/libknowrob.so b/knowrob_connector/lib/libknowrob.so index 32681c3..3b8079f 100755 Binary files a/knowrob_connector/lib/libknowrob.so and b/knowrob_connector/lib/libknowrob.so differ diff --git a/knowrob_connector/lib/libmultiverse_client_json.so b/knowrob_connector/lib/libmultiverse_client_json.so index 09e34cc..81a8dc2 100644 Binary files a/knowrob_connector/lib/libmultiverse_client_json.so and b/knowrob_connector/lib/libmultiverse_client_json.so differ diff --git a/knowrob_connector/owl/USD.owl b/knowrob_connector/owl/USD.owl new file mode 100644 index 0000000..d3b5ed0 --- /dev/null +++ b/knowrob_connector/owl/USD.owl @@ -0,0 +1,1585 @@ + + + + + The purpose of the USD ontology is to establish a graph model of the USD language, and to support translation from USD to a KG representation of scene graphs. To this end, the core vocabulary of USD is defined in terms of an upper-level ontology. In addition, a set of re-usable built-in schemata that are used in the USD language to describe prims are defined. In order to fasciliate translation, the ontological model attempts to replicate the structure of USD as closely as possible while in addition entailing semantics of USD entities. + USD Ontology + 0.1 + 0.1 created by Daniel Beßler and Giang Nguyen. The scope of the ontology is limited to syntactic features of the USD language needed for a usecase scenario (box opening) investigated in the scope of a scientific article. + + + + + + + + + + + + + + + + + + + A vector of three double values. + + + + + + + + A vector of three float values. + + + + + + + + A vector of four float values. + + + + + + + + + + + + + + A 4x4 matrix with double elements. + + + + + + + + + + + + + + A quaternion with float values. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A schematic relation asserting containment, understood in a very broad sense, by one Entity of another. + + + + + + + + + + + + Links prims with API schemata applied to it. + has api + + + + + + + + + + + + + + + + + + + + + + + + + + A transitive and symmetric relation that expresses (indirect) connection between entities. + has connection + + + + + + + + + + + + + A symmetric relation that expresses direct connection between entities. + has direct connection + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Links prims with schemata applied to it. + has schema + + + + + + + + + + + + + + + + + + + + + + + + + Links prims with typed schemata applied to it. + has typed schema + + + + + + + + + + + Links prims with API schemata applied to it. + is api of + + + + + + + + + + + + + + + + + + + + + + A schematic relation asserting containment, understood in a very broad sense, by one Entity of another. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Links prims with schemata applied to it. + is schema of + + + + + + + + + + + + + + + + + + + + + + + Links prims with typed schemata applied to it. + is typed schema of + + + + + + + + + + + + Relationship to body0 + + + + + + + + + + + + Relationship to body1 + + + + + + + + + + + + PhysicsScene that will simulate this body + + + + + + + + + + + + + + + A data value of a color quality. + + + + + + + + + + + Size of the cylinder’s spine + + + + + + + + + + A data value of a physics quality. + + + + + + + + + + + Angular velocity in the prim’s local space + + + + + + + + + + + Joint axis + + + + + + + + + + + Center of mass in the prim’s local space + + + + + + + + + + + Determines if the PhysicsCollisionAPI is enabled + + + + + + + + + + + Density of the object + + + + + + + + + + + Diagonalized inertia tensor along the principal axes + + + + + + + + + + + Gravity direction vector in simulation world space + + + + + + + + + + + Gravity acceleration magnitude in simulation world space + + + + + + + + + + + Relative position of the joint frame to body0’s frame + + + + + + + + + + + Relative position of the joint frame to body1’s frame + + + + + + + + + + + Relative orientation of the joint frame to body0’s frame + + + + + + + + + + + Relative orientation of the joint frame to body1’s frame + + + + + + + + + + + Lower limit + + + + + + + + + + + Mass of the object + + + + + + + + + + + Orientation of the inertia tensor’s principal axes in the prim’s local space + + + + + + + + + + + Determines if this PhysicsRigidBodyAPI is enabled + + + + + + + + + + + Upper limit + + + + + + + + + + + Linear velocity in the prim’s local space + + + + + + + + + + + Display or modeling color + + + + + + + + + + + Opacity + + + + + + + + + + + Radius of the cylinder + + + + + + + + + + A data value of a shape quality. + + + + + + + + + + + Length of each edge + + + + + + + + + + + Order of transformation operations + + + + + + + + + + + Rotation as a quaternion + + + + + + + + + + + Scale factor + + + + + + + + + + + 3D transformation matrix + + + + + + + + + + + Translation vector + + + + + + + + + + + + + + A schema that serves as a API for reading and writing related data. + API schema + + + + + + + + + A schema of prims with a finite spatial extend. + + + + + + + + + + + + + + + + + + + + + + + + + An API used to toggle collision detection of a prim. + + + + + + + + + The quality of having a color. Note this notion should be defined in some external ontology. e.g. SOMA ontology defines a similar notion. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The schema of a cube-shaped prim. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The schema of a cylinder-shaped prim. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A schema that serves as a base class for all schemas of geometric primitives. + + + + + + + + + A joint constrains the motion of objects relative to each other. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + An API used to define properties related to the mass of a prim. + + + + + + + + + The quality of having physical characteristics. Note this notion should be defined in some external ontology. e.g. SOMA ontology defines a similar notion. + + + + + + + + + + + + + + + + + + + + + Contains properties that are used to constrain the motion of prims. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A schema that models general properties used for simulation. + + + + + + + + + A schema that serves as a base class for all prims that possess points, providing common attributes such as normals and velocities. + + + + + + + + + The quality of having points ids. + + + + + + + + + + + + + + + + + + + + A schema that represents points, which can be an efficient means of storing and rendering particle effects comprised of thousands or millions of small particles. + + + + + + + + + + + + + + + + + + 1 + + + + + + + 1 + + + + + + + 1 + + + + + + + 1 + + + + Prims are the primary container objects in USD files. Prims may further contain sub-prims, attributes and relationships (properties). Attributes of prims have typed values that may change over time. Prims and attributes may also have meta data (constant over time). Each prim *may* have at most one typed schema that restricts what data it contains. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + An API used to define standard properties of rigid body dynamics. + + + + + + + + + A scene spatially encloses a set of physical objects. + + + + + + + + + + + + + + + USD Schemas are used to establish concrete representations of data. They entail that a certain set of properties is used for describing some phenomena such as properties used to quantify the mass of an object. As such they describe objects where certain qualities of the object are quantified in a specific way. They may also imply type constraints for objects they describe. + + + + + + + + + The quality of having a shape. Note this notion should be defined in some external ontology. e.g. SOMA ontology defines a similar notion. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The schema of a sphere-shaped prim. + + + + + + + + + + + + + + + + + + + + + + + A scene graph represented in a USD file. + + + + + + + + + A schema used to define the role or purpose of a prim. Also called "IsASchema". Each prim may subscribe to at most one TypedSchema. + Typed schema + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A concrete Xformable schema, meaning that it refers to a concrete object in the scene. + + + + + + + + + + + + + + + + + + + + + A schema of prims that can be transformed in space. + + + + + + diff --git a/knowrob_connector/scripts/multiverse_reasoner_test.py b/knowrob_connector/scripts/multiverse_reasoner_test.py new file mode 100644 index 0000000..dfbdebe --- /dev/null +++ b/knowrob_connector/scripts/multiverse_reasoner_test.py @@ -0,0 +1,82 @@ +from knowrob import * +import json + +InitKnowRob() + +kb = KnowledgeBase("/home/sascha/workspace/multiverse_krr/Multiverse-Knowledge/knowrob_connector/settings/multiverse.json") + +def runQuery(queryStr): + phi = QueryParser.parse(queryStr) + resultStream = kb.submitQuery(phi, QueryContext(QueryFlag.QUERY_FLAG_ALL_SOLUTIONS)) + resultQueue = resultStream.createQueue() + retq = None + result = resultQueue.pop_front() + # print if indicatesEndOfEvaluation() is False + while not result.indicatesEndOfEvaluation(): + if retq is None: + retq = [] + if isinstance(result, AnswerYes): + aux = {} + for substitution in result.substitution(): + variable, term = substitution[1], substitution[2] + svar, sterm = None, None + try: + svar, sterm = str(variable), str(term) + except: + pass + if (svar is not None) and (sterm is not None): + aux[svar] = str(sterm) + retq.append(aux) + elif isinstance(result, AnswerNo): + retq = None + break + result = resultQueue.pop_front() + return retq + +# Write tests for this mockup data (fail if not working) + +# Query position and quaternion of object1 +res = runQuery("position(object1, P), quaternion(object1, Q)") +# Create a List of doubles from the string using json loads +positionList1 = json.loads(res[0]["P"]) +quaternionList1 = json.loads(res[0]["Q"]) +# unit test for the above query +assert positionList1[0] == 1.0 +assert positionList1[1] == 2.0 +assert positionList1[2] == 3.0 +assert quaternionList1[0] == 1.3 +assert quaternionList1[1] == 1.0 +assert quaternionList1[2] == 2.0 +assert quaternionList1[3] == 3.0 + +# Query only position of object2 +res = runQuery("position(object2, P)") +# Create a List of doubles from the string using json loads +positionList2 = json.loads(res[0]["P"]) +# print the result of the query +print(str(positionList2)) +# unit test for the above query +assert positionList2[0] == 3.0 +assert positionList2[1] == 4.0 +assert positionList2[2] == 5.0 + +# Query only quaternion of object2 +res = runQuery("quaternion(object2, Q)") +# Create a List of doubles from the string using json loads +quaternionList2 = json.loads(res[0]["Q"]) +# unit test for the above query +assert quaternionList2[0] == 1.3 +assert quaternionList2[1] == 3.0 +assert quaternionList2[2] == 4.0 +assert quaternionList2[3] == 5.0 + +# Query for non-existing object +res = runQuery("position(object3, P)") +# unit test for the above query +assert res is None + +# Query for non-existing attribute +# TODO: Check why this is not working +# res = runQuery("midichlorian_count(object1, Q)") +# unit test for the above query +# assert res is [] \ No newline at end of file diff --git a/knowrob_connector/settings/multiverse.json b/knowrob_connector/settings/multiverse.json new file mode 100644 index 0000000..061cb7a --- /dev/null +++ b/knowrob_connector/settings/multiverse.json @@ -0,0 +1,52 @@ +{ + "logging": { + "console-sink": { + "level": "debug" + }, + "file-sink": { + "level": "debug" + } + }, + "semantic-web": { + "prefixes": [ + { + "alias": "USD", + "uri": "https://ease-crc.org/ont/USD.owl" + }, + { + "alias": "SOMA", + "uri": "http://www.ease-crc.org/ont/SOMA.owl" + } + ] + }, + "data-sources": [ + { + "path": "owl/USD.owl", + "format": "rdf-xml" + }, + { + "path": "owl/SOMA-Montessori.owl", + "format": "rdf-xml" + } + ], + "data-backends": [ + { + "type": "Redland", + "name": "redland", + "read-only": false + } + ], + "reasoner": [ + { + "type": "MultiverseReasoner", + "name": "multiverse", + "lib": "lib/libknowrob_connector.so", + "data-backend": "redland", + "simulation_name": "knowrob_connector", + "world_name": "world", + "host": "tcp://127.0.0.1", + "server_port": "7000", + "client_port": "2401" + } + ] +} \ No newline at end of file diff --git a/knowrob_connector/src/knowrob_connector.cpp b/knowrob_connector/src/knowrob_connector.cpp index 16a7428..c41a96e 100644 --- a/knowrob_connector/src/knowrob_connector.cpp +++ b/knowrob_connector/src/knowrob_connector.cpp @@ -1,4 +1,6 @@ -#include +#include +#include +#include #include #include @@ -30,12 +32,18 @@ std::map attribute_map_double = { {"force", 3}, {"torque", 3}}; +// list of supported properties +std::set supported_properties = { + "position", + "quaternion"}; + + class MultiverseKnowRobConnector : public MultiverseClientJson { public: MultiverseKnowRobConnector( - const std::string &world_name, - const std::string &simulation_name, + const std::string &world_name, + const std::string &simulation_name, const std::string &in_host, const std::string &in_server_port, const std::string &in_client_port) @@ -51,27 +59,32 @@ class MultiverseKnowRobConnector : public MultiverseClientJson host = in_host; server_port = in_server_port; client_port = in_client_port; + + // create mockup data + // Initialize member arrays instead of local ones + position_1[0] = 1.0; position_1[1] = 2.0; position_1[2] = 3.0; + position_2[0] = 3.0; position_2[1] = 4.0; position_2[2] = 5.0; + quaternion_1[0] = 1.3; quaternion_1[1] = 1.0; quaternion_1[2] = 2.0; quaternion_1[3] = 3.0; + quaternion_2[0] = 1.3; quaternion_2[1] = 3.0; quaternion_2[2] = 4.0; quaternion_2[3] = 5.0; + + receive_objects_data = { + {"object1", + {{"position", {&position_1[0], &position_1[1], &position_1[2]}}, + {"quaternion", {&quaternion_1[0], &quaternion_1[1], &quaternion_1[2], &quaternion_1[3]}}}}, + {"object2", + {{"position", {&position_2[0], &position_2[1], &position_2[2]}}, + {"quaternion", {&quaternion_2[0], &quaternion_2[1], &quaternion_2[2], &quaternion_2[3]}}}}}; + } ~MultiverseKnowRobConnector() { - } public: - std::vector get_receive_object_data(const std::string &object_name, const std::string &attribute_name) + std::map>> get_receive_objects_data() const { - if (receive_objects_data.find(object_name) == receive_objects_data.end()) - { - printf("Object %s not found\n", object_name.c_str()); - return {}; - } - if (receive_objects_data[object_name].find(attribute_name) == receive_objects_data[object_name].end()) - { - printf("Attribute %s not found\n", attribute_name.c_str()); - return {}; - } - return receive_objects_data[object_name][attribute_name]; + return receive_objects_data; } private: @@ -82,7 +95,6 @@ class MultiverseKnowRobConnector : public MultiverseClientJson void wait_for_connect_to_server_thread_finish() override { - } void start_meta_data_thread() override @@ -92,7 +104,6 @@ class MultiverseKnowRobConnector : public MultiverseClientJson void wait_for_meta_data_thread_finish() override { - } bool init_objects(bool) override @@ -133,17 +144,14 @@ class MultiverseKnowRobConnector : public MultiverseClientJson void bind_response_meta_data() override { - } void bind_api_callbacks() override { - } void bind_api_callbacks_response() override { - } void init_send_and_receive_data() override @@ -184,7 +192,6 @@ class MultiverseKnowRobConnector : public MultiverseClientJson void bind_receive_data() override { - } void clean_up() override @@ -209,5 +216,128 @@ class MultiverseKnowRobConnector : public MultiverseClientJson std::map>> receive_objects_data; + double position_1[3]; + double position_2[3]; + double quaternion_1[4]; + double quaternion_2[4]; + double sim_start_time; -}; \ No newline at end of file +}; + + +class MultiverseReasoner : public knowrob::RDFGoalReasoner +{ +public: + MultiverseReasoner(std::string_view) + { + // Use all elements of supported_properties to define relations + for (const std::string &property : supported_properties) + { + defineRelation(knowrob::PredicateIndicator(property, 2)); + } + } + + ~MultiverseReasoner() + { + if (connector != nullptr) + { + delete connector; + } + } + + bool initializeReasoner(const knowrob::PropertyTree &ptree) + { + // Get the world_name, simulation_name, host, server_port, and client_port from the ptree, default values should be null + auto world_name = ptree->get_optional("world_name"); + auto simulation_name = ptree->get_optional("simulation_name"); + auto host = ptree->get_optional("host"); + auto server_port = ptree->get_optional("server_port"); + auto client_port = ptree->get_optional("client_port"); + // Check if any of the values are empty, print individual error messages and return false + if (!world_name.has_value()) + { + KB_ERROR("world_name is not set"); + return false; + } + if (!simulation_name.has_value()) + { + KB_ERROR("simulation_name is not set"); + return false; + } + if (!host.has_value()) + { + KB_ERROR("host is not set"); + return false; + } + if (!server_port.has_value()) + { + KB_ERROR("server_port is not set"); + return false; + } + if (!client_port.has_value()) + { + KB_ERROR("client_port is not set"); + return false; + } + // Create the MultiverseKnowRobConnector object, using std_unique_ptr + connector = new MultiverseKnowRobConnector(world_name.value(), simulation_name.value(), host.value(), server_port.value(), client_port.value()); + return true; + } + + bool evaluate(knowrob::RDFGoalPtr goal) + { + auto literal = goal->rdfLiterals().at(0); + knowrob::TermPtr s = literal->subjectTerm(); + knowrob::TermPtr o = literal->objectTerm(); + knowrob::TermPtr p = literal->propertyTerm(); + // Check if subject is a atom and object is a literal + if (s->isAtomic() && p->isAtomic() && o->isVariable()) + { + // Get var of subject + auto s_atomic = std::static_pointer_cast(s); + // s_atomic->stringForm() to get string + // Get var of object + auto o_var = std::static_pointer_cast(o); + // Check value of property is position + auto p_atomic = std::static_pointer_cast(p); + // Check if the object is in get_receive_objects_data + auto receive_objects_data = connector->get_receive_objects_data(); + if (receive_objects_data.find(std::string(s_atomic->stringForm())) == receive_objects_data.end()) + { + return false; + } + // Check if the property is in the receive_objects_data + auto object_it = receive_objects_data.find(std::string(s_atomic->stringForm())); + if (object_it == receive_objects_data.end() || object_it->second.find(std::string(p_atomic->stringForm())) == object_it->second.end()) + { + return false; + } + // Get the data from the receive_objects_data + auto data = receive_objects_data[std::string(s_atomic->stringForm())][std::string(p_atomic->stringForm())]; + // Create xsdatomics for all the values, then a listterm containing them + // Create xsdatomic for all the values using the create function + std::vector terms; + for (double *value : data) + { + auto x = knowrob::XSDAtomic::create(std::to_string(*value), "http://www.w3.org/2001/XMLSchema#double"); + terms.push_back(x); + } + // Create listterm using the terms + auto result_list = std::make_shared(terms); + + // Create bindings + auto bindings = std::make_shared(); + // Bind the data to the object and attribute + bindings->set(o_var, result_list); + // Return the bindings + goal->push(bindings); + } + return true; + } + +private: + MultiverseKnowRobConnector *connector = nullptr; +}; + +// define the plugin +REASONER_PLUGIN(MultiverseReasoner, "MultiverseReasoner"); \ No newline at end of file