../_images/tiagopro-icon.png ../_images/kangaroo-icon.png ../_images/tiago-icon.png ../_images/ari-icon.png ../_images/talos-icon.png ../_images/mobile-bases-icon.png

How to add/remove/query facts from the knowledge base#

This section describes how to add/remove/query the robotโ€™s knowledge base.

Note

You might want to check first ๐Ÿ’ก Knowledge and reasoning to know more about your robotโ€™s knowledge base.

You have two main options to access the knowledge base:

  • use the Python wrapper, that uses an idiomatic python syntax to add/remove/query facts. If you are programming with Python, we recommend this approach. See section Python API.

  • use the ROS interface directly: the knowledge base exposes standard topics and services to manipulate knowledge. See section ROS API.

Using the knowledge base from Python#

The Python wrapper makes it easy to update or query the knowledge base from a Python script or mission controller.

Our Python wrapper follows closely the API of the pykb library: pykb. pykb examples and documentation are largely applicable here as well.

If not already running, start the knowledge base:

ros2 launch knowledge_core knowledge_core.launch.py

Then, create a new Python script and import the Python wrapper as follows:

 1# first, create a ROS 2
 2import rclpy
 3from rclpy.node import Node
 4
 5rclpy.init()
 6node = Node("test_kb_client")
 7
 8# then import the knowledge base API and create a KB instance
 9from knowledge_core.api import KB
10kb = KB(node)

You can then add/remove statements with kb += "s p o", kb += ["s1 p1 o1", "s2 p2 o2"], kb -="s p o", etc.

Then letโ€™s assume that we want to add the following facts to the kb: โ€œari is-a Robotโ€, โ€œtiago is-a Robotโ€, and โ€œstockbot is-a Robotโ€.

We can do it as it follows:

1kb += ["ari rdf:type Robot",
2       "tiago rdf:type Robot",
3       "stockbot rdf:type Robot"]

We can then query the knowledge base and to retrieve this information:

1for known_robot in kb["?robot rdf:type Robot"]:
2    print(known_robot)

If the facts have been correctly added, you should get ari, tiago, and stockbot as output.

Letโ€™s now remove some facts from the knowledge base. Suppose we want to remove the following facts: tiago rdf:type Robot, and stockbot rdf:type Robot:

1kb -= "tiago rdf:type Robot"
2kb -= "stockbot rdf:type Robot"
3# or equivalently
4# kb -= ["tiago rdf:type Robot", "stockbot rdf:type Robot"]
5
6for known_robot in kb["?robot rdf:type Robot"]:
7    print(known_robot)

If the facts have been correctly removed, you should only get ari as output.

Refer to the Python API for more advanced examples, including subscribing to semantic events (i.e., get notifications when e.g. a specific fact becomes true).

Using the knowledge base with the ROS API#

First, start the knowledge base:

ros2 launch knowledge_core knowledge_core.launch.py

You should see the following output on your terminal:

KnowledgeCore
=============

Knowledge base started.

Available topics:
- /kb/add_fact [std_msgs/String]
- /kb/remove_fact [std_msgs/String]
- /kb/active_concepts [kb_msgs/ActiveConcepts]
- /kb/events/<id> [std_msgs/String] for each subscribed event

Available services:
- /kb/manage [kb_msgs/Manage]
- /kb/revise [kb_msgs/Revise]
- /kb/query [kb_msgs/Query]
- /kb/about [kb_msgs/About]
- /kb/label [kb_msgs/About]
- /kb/details [kb_msgs/About]
- /kb/lookup [kb_msgs/Lookup]
- /kb/sparql [kb_msgs/Sparql]
- /kb/events [kb_msgs/Event]

KnowledgeCore exposes two main topics, /kb/add_fact and /kb/remove_fact, to add/remove triples to the knowledge base. Both topics expect a simple string with 3 tokens separated by spaces (if the object is a literal string, use double quotes to escape it).

Note

The topic, /kb/events/<id>, is used for events: you can subscribe to specific โ€˜semanticโ€™ events (eg, a given fact becomes true), and get notified.

See the KnowledgeCore API documentation for details.

It also exposes several services, including:

  • /kb/revise to add/remove facts using a synchronous interface

  • /kb/query to perform simple queries

  • /kb/manage to manage the knowledge base (including for instance the wipe-off of all the facts)

For more details about the API please refer to the ROS API.

We are now ready to see how we can add, remove and query the knowledge base.

To add facts to the knowledge base, we can do it using the topics or the services. For instance, suppose we want to add the following facts: [ari rdf:type Robot, tiago rdf:type Robot, stockbot rdf:type Robot].

 1import rclpy
 2from rclpy.node import Node
 3from std_msgs.msg import String
 4from kb_msgs.srv import Revise
 5
 6rclpy.init()
 7node = Node("test_kb_client")
 8
 9# add a fact by publishing to the /kb/add_fact topic
10facts_pub = node.create_publisher(String, "/kb/add_fact", 1)
11facts_pub.publish(String(data="ari rdf:type Robot"))
12
13# or using the Revise service
14revise = node.create_client(Revise, "/kb/revise")
15revise.wait_for_service(timeout_sec=1.0)
16
17future = revise.call_async(
18        Revise.Request(
19            statements=["tiago rdf:type Robot",
20                        "stockbot rdf:type Robot"],
21            method=Revise.Request.ADD
22        ))
23
24# wait for the service to complete
25rclpy.spin_until_future_complete(node, future)

We can then query the knowledge base and check if we can retrieve this information.

26import json
27from kb_msgs.srv import Query
28
29query = node.create_client(Query, "/kb/query")
30query.wait_for_service(timeout_sec=1.0)
31
32future = query.call_async(
33        Query.Request(
34            patterns=["?robot rdf:type Robot"],
35            vars=[],
36            models=[]
37        ))
38
39
40# wait for the service to complete
41rclpy.spin_until_future_complete(node, future)
42
43results = future.result()
44
45print(json.loads(results.json))

If the facts have been correctly added, you should get the following output:

[{'robot': 'stockbot'}, {'robot': 'tiago'}, {'robot': 'ari'}]

Letโ€™s now remove some facts from the knowledge base. Suppose we want to remove the following facts: [tiago rdf:type Robot, stockbot rdf:type Robot].

46# either via topics...
47facts_pub = node.create_publisher(String, "/kb/remove_fact", 1)
48facts_pub.publish(String(data="tiago rdf:type Robot"))
49
50# ...or with a service call
51future = revise.call_async(
52        Revise.Request(
53            statements=["stockbot rdf:type Robot"],
54            method=Revise.Request.DELETE
55        ))
56
57rclpy.spin_until_future_complete(node, future)

We can then query the knowledge base again:

58future = query.call_async(
59        Query.Request(
60            patterns=["?robot rdf:type Robot"],
61            vars=[],
62            models=[]
63        ))
64
65rclpy.spin_until_future_complete(node, future)
66
67results = future.result()
68print(json.loads(results.json))

If the facts have been correctly removed, you should get the following output:

[{'robot': 'ari'}]

Next steps#