-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Knowledge #210
Open
Tigul
wants to merge
47
commits into
cram2:dev
Choose a base branch
from
Tigul:knowledge
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Knowledge #210
Changes from all commits
Commits
Show all changes
47 commits
Select commit
Hold shift + click to select a range
8643733
[knowledge] First draft of knowledge source
Tigul 7d16285
[knowledge] Added Knowledge engine
Tigul db8874e
[knowledge] Update architecture for knowledge engine
Tigul 628cf93
[datastructures] Added decision tree implementation
Tigul ec1d66a
[knowledge] Added more knowledge sources
Tigul 827b93c
[DecisionTree] Documentation
Tigul d9b5459
Merge branch 'dev' of github.com:cram2/pycram into knowledge
Tigul 925c479
[aspects] Added aspects and conditions
Tigul 791731a
[designator] Added knowledge pre conditions to pick up
Tigul f42c3c2
Merge branch 'new-robot-description' of github.com:Tigul/pycram-1 int…
Tigul 9d5bcd2
[aspects] New Aspects structure
Tigul fbce04f
[KnowledgeEngine] Method to call source with highest priority
Tigul 025f46a
[Action desig] Fixed Typing
Tigul eb6749a
[Knowledge engine] Aspects and resolution of Aspects
Tigul 646d0d2
[facts knowledge] Reference inmplementation of reasoning
Tigul 138ce54
Merge branch 'dev' of github.com:cram2/pycram into knowledge
Tigul c207645
[Knowledge engine] Variables in Aspects
Tigul 08d47fb
[knowledge] Refactor of knowledge related files
Tigul e20cc27
[Aspects] Small fixes and better exception return
Tigul dba333c
[designator] Removed resolver parameter
Tigul 016474a
[knowledge engine] Correction of facts knowledge
Tigul 575d114
[aspects] New aspect structure
Tigul 916c0ed
[Aspects] Renamed aspect to property
Tigul 693f728
[knowledge/designator] Rename of property usage
Tigul 6652053
[test] Fixed Test for pre-condition
Tigul 9f38f72
[knowledge engine] Added flag to disable knowledge engine
Tigul a4891ac
[doc] Added documentation for knowledge interface
Tigul 84c33f5
[knowledge] Removed input and output variables
Tigul f3db003
[Designator] Removed deprecated Designator class
Tigul 57ca550
[property] Added reasoning result
Tigul 8d00b0a
[Knowledge Engine] Added reasoned parameter matching
Tigul 4df1c49
[action desigs] Added pre and post perform and small refactor
Tigul 9a364e8
[datastructures] Added partial designator class
Tigul 95fcacf
[partial desig] Fixed typing imports
Tigul 88f6bf4
[plan failures] Fixed reasoning and collision errors
Tigul 1948feb
[partial desig] Added filters for None arguments
Tigul 41d98d0
[property] Added some helpful properties and doc
Tigul 847a756
[knowledge engine] Added Reasoning instance and clean up
Tigul 6448a1a
[Designator] Some small methods and doc
Tigul 652aa38
[general] renaming
Tigul 7c05875
[decision tree] Removed file
Tigul da5d3db
[action desig] Rename and first test of new desig resolution
Tigul c314a2b
[knowledge source] Fixed typing
Tigul 12248b2
[doc] Added images and started doc about parameter reasoning
Tigul b30a8b3
Merge branch 'dev' of github.com:cram2/pycram into knowledge
Tigul 61ec3fe
[examples] added knowledge source example
Tigul 516afdb
[example] added property example
Tigul File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
========= | ||
Knowledge | ||
========= | ||
|
||
To be able to perform tasks in unknown environments a robot needs to have a way to reason and access | ||
knowledge about the world. This knowledge can be represented in different ways and formats. In this | ||
chapter we will discuss how PyCRAM access different kinds of knowledge and integrates them with | ||
action designators. | ||
|
||
------- | ||
Concept | ||
------- | ||
The concept of knowledge in PyCRAM is based on the idea that knowledge can be represented in different ways and provided | ||
from different sources which can be specialized for different tasks. These different sources of knowledge are implemented | ||
behind a common interface which provides a set of methods to query the knowledge. This architecture can be seen in the | ||
following image: | ||
|
||
.. image:: ../images/knowledge/knowledge_arch.png | ||
:align: center | ||
:alt: Knowledge Architecture | ||
|
||
The methods provided by the knowledge sources, are called "properties" since they are used to reason about the properties | ||
of entities in the world. Properties can be combined to create more complex expressions which describe conditions | ||
that have to be true at the time an action designator is executed. Let's look at an example explaining this: | ||
|
||
.. code-block:: python | ||
GraspableProperty(ObjectDesignator(...)) | ||
& ReachableProperty(Pose(....)) | ||
|
||
In this example, we have two properties, one that checks if an object is graspable and one that checks if a pose is reachable. | ||
The `&` operator is used to combine the two properties into a single property that checks if both conditions are true at | ||
the same time. This combined property stems from the PickUpAction where the object a robot wants to pick up has to be | ||
reachable for the robot as well as being able to fit into the end effector of the robot. | ||
|
||
Since knowledge sources are usually specialized for a certain task, they do not need to be able to implement all methods | ||
of the interface. This leads to a lot of knowledge sources which all implement a subset of the methods, therefore no | ||
knowledge source can be used to answer all questions. To solve this problem, PyCRAM has a central interface for processing | ||
the combined properties and querying the knowledge sources called the "KnowledgeEngine". The job of the KnowledgeEngine | ||
is to take a combined property and resolve the individual properties to the available knowledge sources which implement | ||
the methods needed to answer the question. The resolved properties are then combined in the same way as the input property | ||
and evaluated. | ||
|
||
This image shows the process of resolving the properties through the knowledge engine: | ||
.. image:: ../images/knowledge/property_resolution.png | ||
:align: center | ||
:alt: Property Resolution | ||
|
||
|
||
|
||
----------------- | ||
Knowledge Sources | ||
----------------- | ||
Knowledge does not have a unified form or representation, it can be available as an SQL database, a Knowledge Graph, | ||
a simple JSON file, etc. To be able to handle a multitude of different representations of knowledge, PyCRAM uses the | ||
concept of Knowledge Sources. A Knowledge Source is a class that implements a set of methods to access knowledge. Therefore, | ||
PyCRAM does not care how the knowledge is accesses or where it is from as as long as the Knowledge Source implements the | ||
abstract methods. | ||
|
||
The methods that a Knowledge Source must implement are some basic methods to manage connecting to the knowledge itself | ||
and more importantly, methods to query the knowledge. Which methods are provided by each knowledge source decides each | ||
knowledge source on its own by using the respective property as a mix-in of the knowledge source. The properties curren | ||
available and which a knowledge source can implement are: | ||
|
||
- `GraspableProperty`: Checks if an object is graspable | ||
- `ReachableProperty`: Checks if a pose is reachable | ||
- `SpaceIsFreeProperty`: Checks if a space is free for the robot to move to | ||
- `GripperIsFreeProperty`: Checks if the gripper is free to grasp an object | ||
- `VisibleProperty`: Checks if an object is visible | ||
|
||
|
||
## TODO link to example of knowledge source | ||
|
||
---------------- | ||
Knowledge Engine | ||
---------------- | ||
The Knowledge Engine is the central component in PyCRAM to reason about the world. It takes a combined property and | ||
resolves the individual properties to the available knowledge sources which implement the methods needed to answer the | ||
question. | ||
|
||
While the properties are resolved they also infer parameter which are needed to execute the action but may not be defined | ||
in the action designator description. For example, the PickUpAction needs an arm to pick up an object with, however, the | ||
arm does not need to be defined in the action designator and can be inferred from the properties and the state of the | ||
world. | ||
|
||
After the properties are resolved, evaluated and the parameters are inferred, the Knowledge Engine grounds the action | ||
in the belief state and tests if the found solution is valid and can achieve the goal. If the solution is valid, the | ||
Knowledge Engine returns the solution and the action designator is performed. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
================================= | ||
Knowledge and Reasoning in PyCRAM | ||
================================= | ||
|
||
The knowledge engine is able to infer parameters of a designator description from the context given by the properties | ||
attached to its parameters. Since the properties are defined for the parameters of a designator description they add | ||
semantic information to the designator description parameters. The knowledge engine is able to utilize this information | ||
to infer the value of a parameter from the context. | ||
|
||
Inference is done very similar to the normal reasoning process where the property function of the designator description | ||
is first resolved and then evaluated. The difference is that we now not only look at the result (if the properties are | ||
satisfied or not) but also a the possible parameter solutions that are generated while reasoning. | ||
|
||
We start again by taking the properties of of the designator description and resolve them. | ||
|
||
.. image:: ../images/knowledge/property_resolve.png | ||
:alt: Source Resolve | ||
:align: center | ||
|
||
We then evaluate the properties and generate the possible parameter solutions. | ||
|
||
.. image:: ../images/knowledge/property_evaluation.png | ||
:alt: Source Evaluate | ||
:align: center |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
======================= | ||
Knowledge Examples | ||
======================= | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
--- | ||
jupyter: | ||
jupytext: | ||
text_representation: | ||
extension: .md | ||
format_name: markdown | ||
format_version: '1.3' | ||
jupytext_version: 1.16.3 | ||
kernelspec: | ||
display_name: Python 3 (ipykernel) | ||
language: python | ||
name: python3 | ||
--- | ||
|
||
# How to create Knowledge Source | ||
This notebook will detail what a knowledge source does, how it works and how you can create your own. | ||
|
||
A knowledge source is part of the wider knowledge system in PyCRAM as explained [here](/knowledge). The purpose of a | ||
knowledge source is to provide an interface to an external knowledge and reasoning system. | ||
|
||
A knowledge source essentially consists of two parts, management methods which take care of connecting to the knowledge | ||
system as well as registering the knowledge source with the knowledge engine and the implementation of the respective | ||
reasoning queries which this knowledge source is able to process. | ||
|
||
In this example we will walk through the process of creating a simple knowledge source and all steps involved in this process. | ||
|
||
## Creating the Knowledge Source structure | ||
|
||
We will start by creating the general structure of the Knowledge Source as well as the management methods. To do this | ||
you have to create a new class which inherits from the ```KnowledgeSource``` class. | ||
|
||
```python | ||
from pycram.knowledge.knowledge_source import KnowledgeSource | ||
|
||
class ExampleKnowledge(KnowledgeSource): | ||
|
||
def __init__(self): | ||
super().__init__(name="example", priority=0) | ||
self.parameter = {} | ||
|
||
def is_available(self) -> bool: | ||
return True | ||
|
||
def is_connected(self) -> bool: | ||
return True | ||
|
||
def connect(self): | ||
pass | ||
|
||
def clear_state(self): | ||
self.parameter = {} | ||
``` | ||
|
||
What we did in the code above was creating a class which inherits from the ```KowledgeSource``` base class, in the | ||
constructor of this new class we initialize the base class with the name of the new Knowledge Source as well as a | ||
priority. The priority is used to determine the order of all Knowledge Sources, in case two Knowledge Sources provide | ||
the same reasoning queries the one with the higher priority is used. | ||
|
||
Furthermore, we define a number of methods that manage the connection to the knowledge system namely the methods | ||
```is_available```, ```is_connected``` and ```connect```. The first two methods just return a bool which states if the | ||
knowledge system is available and connected to this Knowledge Source. The last method is used to create a connection | ||
to the knowledge system. Since this is an example and we are not connecting to an external knowledge system the methods | ||
are fairly trivial. | ||
|
||
The last method we defined is ```clear_state```, this is used to clear any state the knowledge source itself might hold | ||
either of the knowledge system or of this Knowledge Source class itself. | ||
|
||
|
||
# Managing the resolvable Properties | ||
Properties serve two purposes in the management of knowledge in PyCRAM, the first is to define semantic properties of | ||
parameter of action designator. The second is to specify which properties or knowledge queries a Knowledge Source can | ||
answer. | ||
|
||
To define which properties a Knowledge Source can handle we simply use the respective properties as mix-in for the class | ||
definition. With this let's take another look at our Knowledge Source with the handling of two properties. | ||
|
||
```python | ||
from pycram.knowledge.knowledge_source import KnowledgeSource | ||
from pycram.datastructures.property import ReachableProperty, SpaceIsFreeProperty | ||
from pycram.datastructures.world import World | ||
from pycram.datastructures.pose import Pose | ||
from pycram.datastructures.dataclasses import ReasoningResult | ||
from pycram.costmaps import OccupancyCostmap | ||
from pycram.ros.logging import loginfo | ||
import numpy as np | ||
|
||
class ExampleKnowledge(KnowledgeSource, ReachableProperty, SpaceIsFreeProperty): | ||
|
||
def __init__(self): | ||
super().__init__(name="example", priority=0) | ||
self.parameter = {} | ||
|
||
def is_available(self) -> bool: | ||
return True | ||
|
||
def is_connected(self) -> bool: | ||
return True | ||
|
||
def connect(self): | ||
pass | ||
|
||
def clear_state(self): | ||
self.parameter = {} | ||
|
||
def reachable(self, pose: Pose) -> ReasoningResult: | ||
loginfo(f"Checking reachability for pose {pose}") | ||
robot_pose = World.robot.pose | ||
distance = pose.dist(robot_pose) | ||
return ReasoningResult(distance < 0.6) | ||
|
||
def space_is_free(self, pose: Pose) -> ReasoningResult: | ||
loginfo(f"Checking if the space is free around {pose}") | ||
om = OccupancyCostmap(0.2, False, 100, 0.02, pose) | ||
return ReasoningResult(np.sum(om.map) == 6561) | ||
``` | ||
|
||
Now we extend our Knowledge Source with the capability to handle two properties, Reachable and SpaceIsFree. As you can | ||
see all we needed to do for this is to use the respective properties as mix-ins besides the Knowledge Source as well as | ||
implement the method for each property which does the actual reasoning. | ||
|
||
In this case the reasoning is kept fairly simple, since this is not the objective of this example. Reachable just | ||
checks if a pose is within 60 centimeters of the robot while SpaceIsFree checks if a 2x2 meter square around the given | ||
pose has no obstacles. | ||
|
||
The methods doing the reasoning have to return a ```ReasoningResult``` instance, which contains a bool stating if the | ||
reasoning succeeded or failed as well as additional parameters which might be inferred during reasoning. The additional | ||
parameters are stated as key-value pairs in a dictionary. | ||
|
||
|
||
# Testing the Knowledge Source | ||
Since we now have a Knowledge Source which also implements two properties we can check if the Knowledge Source is used | ||
to resolve the correct properties. | ||
|
||
For this test we need a world as well as a robot. | ||
|
||
```python | ||
from pycram.worlds.bullet_world import BulletWorld | ||
from pycram.world_concepts.world_object import Object | ||
from pycram.datastructures.enums import WorldMode, ObjectType | ||
from pycram.knowledge.knowledge_engine import KnowledgeEngine | ||
|
||
world = BulletWorld(WorldMode.GUI) | ||
pr2 = Object("pr2", ObjectType.ROBOT, "pr2.urdf") | ||
|
||
target_pose = Pose([0.3, 0, 0.2]) | ||
property = ReachableProperty(target_pose) & SpaceIsFreeProperty(target_pose) | ||
|
||
ke = KnowledgeEngine() | ||
resolved_property = ke.resolve_properties(property) | ||
|
||
print(f"Result of the property: {resolved_property()}") | ||
``` | ||
|
||
As you can see we created a ```ReachableProperty``` as well as a ```SpaceIsFreeProperty``` and resolved them. For more | ||
details on how properties and their resolution work please referee to the properties example. | ||
|
||
Afterwards, we execute the properties, here we can see the logging infos from our Knowledge Source as well as the | ||
confirmation that the implementation for both properties worked correctly. | ||
|
||
```python | ||
world.exit() | ||
``` |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is the inclusion of the example missing here?