UML – ROSPlann Knowledge base – formal ROS description
Contents
This document has been written in order to support the develop of the package, as well as both the coding and the testing phases.
schema – knowledge base
here are the main services exposed by the ROSPlan knowledge base. The graph shows the ones used by this project.
schema – CLASS kb_tools
Todo
the current version has a very poor support for the PDDL fluents, because not required by this kind of project.
the class kb_tools is used for interacting in a convenient way with the knowledge base. It contains methods for enabling another class (by inheritance) both to read and write to the Knowledge Base. This little schema reports the most important methods provided by the class.
(from here) The long list of HOW TOs
here’s a short summary about how to deal with the Knowledge Base. Mostly of the snippets introduced here are written in C++ without loss of generality.
HOW TO read a predicate
libraries to import:
#include "diagnostic_msgs/KeyValue.h"
#include "rosplan_knowledge_msgs/KnowledgeItem.h"
#include "rosplan_knowledge_msgs/KnowledgeQueryService.h"
// kb knowledge type
#define KB_KTYPE_FLUENT 2
#define KB_KTYPE_PREDICATE 1
the client to open:
#define SERVICE_QUERY "/rosplan_knowledge_base/query_state"
ros::ServiceClient cl_query = nh.serviceClient<rosplan_knowledge_msgs::KnowledgeQueryService>( SERVICE_QUERY );
a more detailed way to open the service:
#define SERVICE_QUERY "/rosplan_knowledge_base/query_state"
// === Predicates Query service === //
TLOG( "Opening client " << LOGSQUARE( SERVICE_QUERY ) << "..." );
ros::ServiceClient cl_query = nh.serviceClient<rosplan_knowledge_msgs::KnowledgeQueryService>( SERVICE_QUERY );
if( !this->cl_query.waitForExistence( ros::Duration( TIMEOUT_QUERY ) ) )
{
TERR( "unable to contact the server - timeout expired (" << TIMEOUT_QUERY << "s) " );
// return;
}
TLOG( "Opening client " << LOGSQUARE( SERVICE_QUERY ) << "... OK" );
message rosplan_knowledge_msgs/KnowledgeQueryService
rosplan_knowledge_msgs/KnowledgeItem[] knowledge
---
bool all_true
bool[] results
rosplan_knowledge_msgs/KnowledgeItem[] false_knowledge
message rosplan_knowledge_msgs/KnowledgeItem
(needed to perform the request)
# A knowledge item used to represent a piece of the state in ROSPlan
uint8 INSTANCE = 0
uint8 FACT = 1
uint8 FUNCTION = 2
uint8 EXPRESSION = 3
uint8 INEQUALITY = 4
uint8 knowledge_type
# time at which this knowledge becomes true
time initial_time
# knowledge is explicitly false
bool is_negative
#---------
# INSTANCE
#---------
# instance knowledge_type
string instance_type
string instance_name
#----------------------
# PREDICATE OR FUNCTION
#----------------------
# attribute knowledge_type
string attribute_name
diagnostic_msgs/KeyValue[] values
#---------
# FUNCTION
#---------
# function value
float64 function_value
#-----------
# EXPRESSION
#-----------
string optimization
rosplan_knowledge_msgs/ExprComposite expr
#-----------
# INEQUALITY
#-----------
rosplan_knowledge_msgs/DomainInequality ineq
message diagnostic_msgs/KeyValue
# what to label this value when viewing
string key
# a value to track over time
string value
how to perform the reading
reading predicates : if you’re sure that the predicate you’re asking for is unique, use the field response.all_true; or also .response.results[] showing each truth value.
// data for request
std::string pname
std::map<std::string, std::string> params
// === PREPARE THE REQUEST === //
rosplan_knowledge_msgs::KnowledgeQueryService query;
rosplan_knowledge_msgs::KnowledgeItem kbm;
kbm.knowledge_type = KB_KTYPE_PREDICATE; // it corresponds to 1
kbm.attribute_name = pname; // the name of the predicate
for ( auto it=params.begin( ) ; it!=params.end( ) ; ++it )
{
diagnostic_msgs::KeyValue kv;
kv.key = it->first;
kv.value = it->second;
kbm.values.push_back( kv );
}
query.request.knowledge.push_back( kbm );
// ... the same thing for each predicate you want
// n predicate in list -> n values inside the result
// === PERFORM THE REQUEST === //
cl_query.call( query );
// === EVALUATE THE RESULT === //
bool res = false;
if( query.response.results.size() == 1 )
{
// only one predicate compatible
// method 1
res = query.response.results[0];
// method 2
res = query.response.all_true;
}
else
{
// many predicates (many results...)
}
how to perform the reading using KB tools
// just one predicate!
std::string pname
std::map<std::string, std::string> params
kb_tools kbt;
bool res = kbt.get_predicate( pname, params );
if(!kbt->ok())
ROS_ERR("kb tools get predicate");
HOW TO modify a predicate
libraries:
#include "diagnostic_msgs/KeyValue.h"
#include "rosplan_knowledge_msgs/KnowledgeItem.h"
#include "rosplan_knowledge_msgs/KnowledgeUpdateService.h"
// kb knowledge type
#define KB_KTYPE_FLUENT 2
#define KB_KTYPE_PREDICATE 1
// kb action
#define KB_ADD_KNOWLEDGE 0
#define KB_DEL_KNOWLEDGE 2
the service to interact with:
#define SERVICE_KB_UPDATE "/rosplan_knowledge_base/update"
ros::ServiceClient cl_kb_update = nh.serviceClient<rosplan_knowledge_msgs::KnowledgeUpdateService>( SERVICE_KB_UPDATE );
a more detailed way to open the service:
#define SERVICE_KB_UPDATE "/rosplan_knowledge_base/update"
// === update service === //
TLOG( "Opening client " << LOGSQUARE( SERVICE_KB_UPDATE ) << "..." );
ros::ServiceClient cl_kb_update = nh.serviceClient<rosplan_knowledge_msgs::KnowledgeUpdateService>( SERVICE_KB_UPDATE );
if( !this->cl_kb_update.waitForExistence( ros::Duration( TIMEOUT_KB_UPDATE ) ) )
{
TERR( "unable to contact the server - timeout expired (" << TIMEOUT_KB_UPDATE << "s) " );
this->success = false;
return;
}
TLOG( "Opening client " << LOGSQUARE( SERVICE_KB_UPDATE ) << "... OK" );
service rosplan_knowledge_msgs::KnowledgeUpdateService
uint8 update_type
rosplan_knowledge_msgs/KnowledgeItem knowledge
---
bool success
message rosplan_knowledge_msgs/KnowledgeItem (see above)
message diagnostic_msgs/KeyValue (see above)
how to perform the update
std::string pname
std::map<std::string, std::string> params
bool val = false; // the new val for the predicate
// === PREPARE THE REQUEST === //
rosplan_knowledge_msgs::KnowledgeUpdateService kbm;
kbm.request.update_type = ( val ? KB_ADD_KNOWLEDGE : KB_DEL_KNOWLEDGE );
kbm.request.knowledge.knowledge_type = KB_KTYPE_PREDICATE;
kbm.request.knowledge.attribute_name = pname;
for ( auto it=params.begin( ) ; it!=params.end( ) ; ++it )
{
diagnostic_msgs::KeyValue kv;
kv.key = it->first;
kv.value = it->second;
kbm.request.knowledge.values.push_back( kv );
}
// === PERFORM THE REQUEST === //
cl_kb_update.call( kbm );
// === EVALUATE THE RESULT === //
bool success = kbm.response.success;
how to perform the update with kb_tools:
std::string pname
std::map<std::string, std::string> params
bool val = false; // the new val for the predicate
kb_tools kbt;
bool res = kbt.set_predicate( pname, params, val );
if(!kbt->ok())
ROS_ERR("kb tools set predicate");
dealing with goals
libraries:
#include "diagnostic_msgs/KeyValue.h"
#include "rosplan_knowledge_msgs/KnowledgeItem.h"
#include "rosplan_knowledge_msgs/KnowledgeUpdateService.h"
// kb knowledge type
#define KB_KTYPE_FLUENT 2
#define KB_KTYPE_PREDICATE 1
// kb action
#define KB_ADD_KNOWLEDGE 0
#define KB_DEL_KNOWLEDGE 2
#define KB_ADD_GOAL 1
#define KB_DEL_GOAL 3
message rosplan_knowledge_msgs/KnowledgeUpdate (see above)
in order to make this update, open a client with /rosplan_knowledge_base/update
of type rosplan_knowledge_msgs::KnowledgeUpdate
#define SERVICE_KB_UPDATE "/rosplan_knowledge_base/update"
ros::ServiceClient cl_kb_update = nh.serviceClient<rosplan_knowledge_msgs::KnowledgeUpdateService>( SERVICE_KB_UPDATE );
here’s the code for the action:
std::string pname
std::map<std::string, std::string> params
bool val = false; // the new val for the predicate
// === PREPARE THE REQUEST === //
rosplan_knowledge_msgs::KnowledgeUpdateService kbm;
kbm.request.update_type = ( value ? KB_ADD_GOAL : KB_DEL_GOAL );
kbm.request.knowledge.knowledge_type = KB_KTYPE_PREDICATE;
kbm.request.knowledge.attribute_name = pname;
for ( auto it=params.begin( ) ; it!=params.end( ) ; ++it )
{
diagnostic_msgs::KeyValue kv;
kv.key = it->first;
kv.value = it->second;
kbm.request.knowledge.values.push_back( kv );
}
// === PERFORM THE REQUEST === //
cl_kb_update.call( kbm );
// === EVALUATE THE RESULT === //
bool success = kbm.response.success;
schema – NODE kb_interface
this ROS node provides functionalities for replanning and for altering/reading the knowledge base in a convenient, general way, not constraining the other nodes to take into account the peculiarities of the current PDDL. This makes the system more flexible and adaptable to other types of PDDL problems.
The node takes advantage of the class kb_tools which is applied to handle the data inside the kb.