KnowRob is a knowledge processing system designed for robots. Its purpose is to equip robots with the capability to organize information in re-usable knowledge chunks, and to perform reasoning in an expressive logic. It further provides a set of tools for visualization and acquisition of knowledge.
Knowledge is stored in a graph using a given ontology and ... . Users can query this graph using KnowRobs interfaces from their own applications.
The core of KnowRob is an extendible querying interface that provides basic operations ask, tell, forget, and remember. Their argument is some statement written in the KnowRob Querying Language. Language phrases are terms whose semantics is defined in form of Prolog rules using special operators such as ?> (the ask operator), or +> (the tell operator).
One useful CLI for queries is launched with rosrun rosprolog rosprolog_commandline.py
KnowRob structures knowledge according to models represented using RDF. Some models are very basic and domain-independent such as the OWL model that e.g. distinguishes between object and datatype properties, or the toplevel ontology SOMA which is supported by KnowRob. KnowRob Models is a collection of such models that are explicitely supported by KnowRob. However, support for other models may be added through plugins.
Knowledge is represented in form of temporalized triples -- each subject-predicate-object triple has an additional field that restricts the temporal scope in which the statement represented by the triple is true. A configurable knowledgeGraph is used to store and retrieve temporalized triples -- as a falback implementation, KnowRob provides a simple MongoDB implementation of a temporalized triple store.
One important aspect in knowledge representation for robots is that a lot of knowledge is implicitly encoded in the control structures of the robot. Hence, one goal is to make the knowledge in robot control structures explicit. KnowRob does that through Ontology-based Data Access (OBDA). So called, semantic data accessors are used to map data to symbols in an ontology, often by accessing some database, or by reading from a message queue, etc.
For more information on database backends in KnowRob, please have a look here.
KnowRob uses an ensemble of reasoners approach where inferences of different reasoners are combined into correlated knowledge pieces. The reason for choosing this approach is that there is no single formalism that is suited for every reasoning tasks. Instead, given a problem, one should decide what the most suitable formalism is to tackle it. Consequently, KnowRob can be configured to solve specific problems by loading corresponding reasoning modules that implement a common interface. KnowRob also ships with a set of reasoning modules including an (incomplete) OWL reasoner, a SWRL reasoner, and some specialized reasoning modules that handle domain-specific problems such as reasoning about time intervals using Allen's interval calculus. More complete information about reasoning in KnowRob can be found here.
- SWI Prolog >= 8.2.4
- mongo DB server >= 4.4 and libmongoc
- spdlog
- Raptor2
- fmt
- ROS (ROS noetic for the master branch)
These instructions will get you a copy of KnowRob up and running on your local machine.
KnowRob requires SWI Prolog's latest stable version 8.2.4 or higher. The latest version shipped with Ubuntu 20.04 or older is 7.6.4, so you might need to manually update the library.
# Install from apt
sudo apt install swi-prolog
# Check the version
swipl --version
# If it's under 8.2.4, add the ppa of the latest stable version and update
sudo apt-add-repository -y ppa:swi-prolog/stable
sudo apt update
# upgrade
sudo apt install swi-prolog
KnowRob requires version 4.4 or higher. If your version is lower you will need to update.
Newer versions are not compatible with old DBs and won't allow the mongodb service to start. To avoid issues later, a complete re-installation of the newer version is performed, which requires wiping, dumping or restoring all existing DBs. As this will delete all previous deps, settings and DBs, you should store them before starting the update. Instructions partly taken from here.
# Install mongodb
sudo apt install libmongoc-dev libmongoc-1.0-0
# Check the mongodb version
mongod --version
# If below 4.4, an update is needed.
# ! Store your DBs before proceeding !
# Stop the service
sudo systemctl stop mongod.service
# Remove all DBs
sudo rm -r /var/log/mongodb
sudo rm -r /var/lib/mongodb
# Uninstall all mongo packages
# Be aware that this also removes unrelated packages starting with 'mongo*'
sudo apt purge mongo*
## Install version 4.4
# Add the source, should return 'OK'
curl -fsSL https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list
# Update references and install mongodb
sudo apt update
sudo apt install mongodb-org
# Troubleshoot: If dpkg errors occurr, the deps still refer to old versions. Force the new version
# Replace the <version> with your own new version. To this day it is '4.4.25'.
sudo dpkg -i --force-overwrite /var/cache/apt/archives/mongodb-org-tools_4.4.<version>_amd64.deb
# Try to run the mongodb service
sudo systemctl start mongod.service
# Check if the service is running properly
sudo systemctl status mongod.service
# Refer to the mongodb error code explaination for further insight:
# https://github.com/mongodb/mongo/blob/master/src/mongo/util/exit_code.h
# Status 62 identifies old DBs in /var/log and /var/lib, so delete them.
# To instead keep them, you'll need to downgrade mongo, dump DBs, upgrade mongo, recreate DBs.
# When it fails to open /var/log/mongodb/mongod.log the permissons for that file are incorrect.
# Either set owner and group of these two paths to mongodb, or reinstall mongodb.
(Tested using a WSL2 and Windows 11)
sudo apt update
sudo apt install libspdlog-dev raptor2-utils libraptor2-dev libfmt-dev
Follow these instructions to install ROS Noetic on your machine. Only required if you want to use catkin and ROS tools.
To build knowrob, you will need to add this repository to your catkin workspace. Then proceed by executing
catkin build knowrob
If you encounter errors regarding SWI Prolog or MongoDB versions, redo the install process and try again. Remember to
catkin clean knowrob
If the package still does not build, try modifying the CMakeList.txt slightly, save and build again. Your build process might still be compromised by old errors and this restarts the build from scratch.
To launch the basic example, type
roslaunch knowrob knowrob.launch
You should see something like
# ROS Startup
...
setting /run_id to 1fa113aa-887c-11ee-8552-00155d76860c
process[rosout-1]: started with pid [19352]
started core service [/rosout]
process[knowrob_ros-2]: started with pid [19355]
[15:41:59.227] [info] Using knowledge graph `mongodb` with type `MongoDB`.
[15:41:59.620] [info] dropping graph with name "user".
[15:41:59.621] [info] Using reasoner `mongolog` with type `Mongolog`.
[15:41:59.663] [info] common foreign Prolog modules have been registered.
## The following will only appear on the first startup or when u delete the mongodb base
[15:42:00.285] [info] Loading ontology at '/home/your_user/catkin_ws/src/knowrob/owl/rdf-schema.xml' with version "Mon Nov 20 11:56:29 2023" into graph "rdf-schema".
[15:42:00.304] [info] Loading ontology at '/home/your_user/catkin_ws/src/knowrob/owl/owl.rdf' with version "Mon Nov 20 11:56:54 2023" into graph "owl".
[15:42:00.329] [info] Loading ontology at '/home/your_user/catkin_ws/src/knowrob/owl/test/swrl.owl' with version "Mon Nov 20 11:56:54 2023" into graph "swrl".
If your output looks more like this, the mongoDB server is not running.
[15:44:50.789] [info] Using knowledge graph `mongodb` with type `MongoDB`.
[15:45:20.791] [error] failed to load a knowledgeGraph: mng_error(create_index_failed,No suitable servers found: `serverSelectionTimeoutMS` expired: [connection refused calling ismaster on 'localhost:27017'])
[15:45:20.791] [info] Using reasoner `mongolog` with type `Mongolog`.
[15:45:20.791] [error] failed to load a reasoner: Reasoner `mongolog` refers to unknown data-backend `mongodb`.
On native linux systems, you can enable the service using systemd:
# Try to run the mongodb service
sudo systemctl start mongod.service
# Check if the service is running properly
sudo systemctl status mongod.service
On a WSL2 machine you will need to manually launch a mongoDB server as .systemd does not exist in WSL2. To launch a seperate mongoDB process, execute the following commands in a new terminal (taken from here):
# (once initially) create a directory for the mongoDB data
sudo mkdir -p ~/data/db
# launch mongoDB server with the created path as argument
sudo mongod --dbpath ~/data/db
If you now re-launch this example, you should see the expected output.
Once knowrob is launched, it provides four actions to ask queries:
- askone
- askincremental
- askall
- tell
We provide both a C++ (and Python) library for you to include in your own project. They implement the action client interface to access knowrob data.
To include the library in your own project, just add 'knowrob' to your CMakeLists.txt. Remember to also include the 'target_link_libraries' tag for your executable.
find_package(catkin REQUIRED COMPONENTS
roscpp
...
knowrob)
Then you should be able to create a KnowrobClient instance and use the provided functions:
// include the library
#include "knowrob/ros_client/cpp/knowrob_client.hpp"
// create the KnowrobClient instance
ros::Nodehandle nh;
KnowrobClient m_kc;
kc.initialize(nh);
// prepare a query
KnowrobQuery single_query = kc.getDefaultQueryMessage();
single_query.queryString = std::string("test:hasSon(A,B)");
// send and get the answer
std::vector<KnowrobAnswer> multi_answer;
bool com_success = kc.askAll(single_query, multi_answer);
// inspect the answer
...
To retrieve the answer from knowrob, you should use the type tag to identify the correct value field. See this example implementation from the KnowrobClient:
std::string KnowrobClient::getAnswerText(const KnowrobAnswer& answer) const
{
std::stringstream ss;
int i = 0;
for(auto& elem : answer.substitution)
{
ss << "[" << i << "]" << "\t"
<< "[Key]=" << elem.key << "\t"
<< "[Value]=";
switch(elem.type)
{
case knowrob::KeyValuePair::TYPE_STRING:
{
ss << elem.value_string;
}
break;
case knowrob::KeyValuePair::TYPE_FLOAT:
{
ss << elem.value_float;
}
break;
case knowrob::KeyValuePair::TYPE_INT:
{
ss << elem.value_int;
}
break;
case knowrob::KeyValuePair::TYPE_LONG:
{
ss << elem.value_long;
}
break;
case knowrob::KeyValuePair::TYPE_VARIABLE:
{
ss << elem.value_variable;
}
break;
case knowrob::KeyValuePair::TYPE_PREDICATE:
{
ss << elem.value_predicate;
}
break;
case knowrob::KeyValuePair::TYPE_LIST:
{
ss << elem.value_list;
}
break;
default:
ROS_ERROR_STREAM(m_logger_prefix << "Unknown Answer Substitution Type!");
return std::string("ERROR");
break;
}
ss << std::endl;
}
return ss.str();
}
We also provide an example node that asks and tells queries to knowrob. This demonstrates how the client interface can and should be used. With knowrob launched, you should receive the following output when starting the client node.
user@machine: rosrun knowrob client-node
[ INFO] [1701440166.477513145]: [KCN] Starting the knowrob client node..
[ INFO] [1701440167.479320945]: [KR-RC] Verbose enabled!
[ INFO] [1701440167.479469534]: [KR-RC] Initializing client interfaces..
[ INFO] [1701440167.479821324]: [KR-RC] Query timeout is set to 0s
[ INFO] [1701440167.488575257]: [KR-RC] Waiting for actionserver to start.. Topic = knowrob/askone
[ INFO] [1701440167.739357113]: [KR-RC] Server is ready!
[ INFO] [1701440167.747524053]: [KR-RC] Waiting for actionserver to start.. Topic = knowrob/askall
[ INFO] [1701440168.032018335]: [KR-RC] Server is ready!
[ INFO] [1701440168.042977031]: [KR-RC] Waiting for actionserver to start.. Topic = knowrob/tell
[ INFO] [1701440168.316651395]: [KR-RC] Server is ready!
[ INFO] [1701440168.316746464]: [KR-RC] Init complete!
[ INFO] [1701440168.316788252]: [KCN] Sending AskAll Query: test:hasSon(A,B)
[ INFO] [1701440168.318804522]: [KR-RC] Action finished!
[ WARN] [1701440168.318879392]: [KR-RC] Ask All - Answers vector is empty!
[ERROR] [1701440168.318955555]: [KCN] AskAll false!
[ INFO] [1701440168.319020356]: [KCN] Sending Tell Query: test:hasSon(a,b)
[ INFO] [1701440169.320373169]: [KR-RC] Action finished!
[ INFO] [1701440169.320440014]: [KCN] Tell true!
[ INFO] [1701440169.320481001]: [KCN] Sending AskAll Query: test:hasSon(A,B)
[ INFO] [1701440170.322107486]: [KR-RC] Action finished!
[ INFO] [1701440170.322165765]: [KCN] AskAll true!
[ INFO] [1701440170.322221109]: [KCN] Best Answer is: [0] [Key]=A [Value]=a
[1] [Key]=B [Value]=b
- Sourcecode documentation is available here