Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
doc:reasoning_about_objects [2014/06/05 11:38] – external edit 127.0.0.1doc:reasoning_about_objects [2016/04/19 08:11] (current) – [Visualize the environment, including CAD models of objects] daniel86
Line 1: Line 1:
 ====== Reasoning about objects ====== ====== Reasoning about objects ======
 +~~NOTOC~~
 +\\
 +^ This page describes the 'catkinized' version of KnowRob that uses the [[http://wiki.ros.org/catkin/|catkin buildsystem]] and the pure Java-based [[http://wiki.ros.org/rosjava|rosjava]]. The documentation for the older version, which was based on the rosbuild buildsystem and rosjava_jni, can be found [[/doc/reasoning_about_objects?rev=1407309271|here]].^
 +\\
  
 Before starting this tutorial, you should have completed the following ones: Before starting this tutorial, you should have completed the following ones:
Line 5: Line 9:
   * [[Loading files and ROS packages]]   * [[Loading files and ROS packages]]
  
-===== Load environment specification ===== +===== Load an environment specification ===== 
-We have split the description of the semantic environment map from the set of (smaller) objects in the environment. In realistic applications, the map will be rather static, while the set of objects is usually detected by the robot during operation and updated over time. With the following commands, you can launch KnowRob including the semantic map of the IAS kitchen, and then load the OWL file containing a set of demo objects: +We have separated the semantic environment map and the set of (smaller) objects inside the environment, such as objects inside the cupboards and drawers. This is commonly a good practice since it allows to use the same (often mostly static) map in different settings. In real tasks, the set of objects is usually detected by the robot during operation and updated over time, but for testing purposes, we load some objects from a file 
-<code> + 
- roscd knowrob_basics_tutorial +With the following commands, you can launch KnowRob including the semantic map of our laboratory kitchen, and then load the OWL file containing a set of demo objects. You need to have the knowrob_tutorials repository in your catkin workspace. 
- rosrun rosprolog rosprolog knowrob_basics_tutorial +<code prolog
- owl_parse('owl/ccrl2_map_objects.owl', false, false, true).+?- rosrun rosprolog rosprolog knowrob_basics_tutorial 
 +?- owl_parse('package://knowrob_map_data/owl/ccrl2_semantic_map.owl'). 
 +?- owl_parse('package://knowrob_basics_tutorial/owl/ccrl2_map_objects.owl').
 </code> </code>
-This assumes that the [[https://github.com/knowrob/knowrob_tutorials|knowrob_tutorials stack]] is installed in your ROS environment. If you need to create or edit a semantic map, you can either use the graphical [[semantic_map_editor|Semantic Map editor]] or the [[http://ias.in.tum.de/kb/wiki/index.php/Mod_semantic_map#SemanticMapToOWL|SemanticMapToOWL service]] using the SemMap message. 
  
-===== Load CAD model definition for objects ===== 
  
-Some of the objects in the demo set have CAD models attached. They are used for visualization as well as for reasoning (see below). These models are automatically used when they are specified for either a complete class of objects (using an OWL hasValue restriction) or for an object instance as shown below: +===== Visualize the environment, including CAD models of objects ===== 
-<code> + 
- <owl:NamedIndividual rdf:about="&map_obj;milk1"> +{{ :map-fmi-hospital-room.png?nolink&400|}} 
-     <rdf:type rdf:resource="&knowrob;CowsMilk-Product"/> + 
-     <knowrob:widthOfObject rdf:datatype="&xsd;double">0.1</knowrob:widthOfObject> +Once the map and the example objects have been loaded, you can start the visualization canvas, [[http://localhost:1111|open the web-based visualization in your browser]], and add the objects to this 3D canvas. If definitions for CAD models of objects are loaded, these models are automatically used for visualizing object instances. Otherwise, the system uses grey boxes as default visualization models
-     <knowrob:depthOfObject rdf:datatype="&xsd;double">0.1</knowrob:depthOfObject> + 
-     <knowrob:heightOfObject rdf:datatype="&xsd;double">0.25</knowrob:heightOfObject> +Please make sure that you have launched the 'rosbridge' server in another terminal using
-     <knowrob:pathToCadModel rdf:datatype="&xsd;string"+<code bash
-                             package://knowrob_tutorial/cad/milk.kmz</knowrob:pathToCadModel> +roslaunch rosbridge_server rosbridge_websocket.launch
- </owl:NamedIndividual>+
 </code> </code>
  
-The %%package://...%% identifier references files inside ROS packages. 
  
-===== Visualize environment including object CAD models =====+You can then send the following commands from your KnowRob shell: 
 +<code prolog> 
 +?- visualisation_server.
  
-{{ :map-fmi-hospital-room.png?nolink&400|}}+% Ignore the INFO output on the console 
 +% Open your browser at http://localhost:1111
  
-Once the respective CAD model definitions are loaded, they are automatically used for visualizing object instances instead of the default primitive models (boxescylinders etc). You should see a map including CAD models such as the following when calling: +?- owl_individual_of(Mapknowrob:'SemanticEnvironmentMap'), marker_update(object(Map)).
-<code> +
- visualisation_canvas(_).+
 </code> </code>
 Similarly, we can also visualize small objects in the kitchen: Similarly, we can also visualize small objects in the kitchen:
-<code>+<code prolog>
  (owl_individual_of(A, knowrob:'FoodUtensil');  (owl_individual_of(A, knowrob:'FoodUtensil');
   owl_individual_of(A, knowrob:'FoodVessel');   owl_individual_of(A, knowrob:'FoodVessel');
  owl_individual_of(A, knowrob:'FoodOrDrink')),  owl_individual_of(A, knowrob:'FoodOrDrink')),
- add_object(A, _).+ marker_update(object(A)).
 </code> </code>
 +
 +
 ===== Query for objects with certain properties ===== ===== Query for objects with certain properties =====
  
 Since all objects in the map are instances of the respective object classes, one can query for objects that have certain properties or belong to a certain class, for example: Since all objects in the map are instances of the respective object classes, one can query for objects that have certain properties or belong to a certain class, for example:
-<code> +<code prolog
- % perishable objects: +% perishable objects: 
- ?- owl_individual_of(A, knowrob:'Perishable'). +?- owl_individual_of(A, knowrob:'Perishable'). 
- A = 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#butter1'+A = map_obj:'butter1'
- A = 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#buttermilk1'+A = map_obj:'buttermilk1'
- A = 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#cheese1'+A = map_obj:'cheese1'
- A = 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#milk1' ; +A = map_obj:'milk1' ; 
- A = 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#yogurt1' ; +A = map_obj:'yogurt1'
- A = 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#sausage1'+A = map_obj:'sausage1' 
 + 
 +% all HandTools (e.gsilverware) 
 +?- owl_individual_of(A, knowrob:'HandTool'). 
 +A = map_obj:'knife1' ; 
 +A = map_obj:'fork1' 
 + 
 +% all FoodVessels (i.epieces of tableware) 
 +?- owl_individual_of(A, knowrob:'FoodVessel'). 
 +A = map_obj:'cup1' ; 
 +A = map_obj:'plate1'
 +A = map_obj:'saucer1' 
 + 
 +% everything with a handle: 
 +?- owl_has(A, knowrob:properPhysicalParts, H),  
 +   owl_individual_of(H,  knowrob:'Handle'). 
 +A = map_obj:'Dishwasher37', 
 +H = map_obj:'Handle145' 
 +[...] 
 +</code> 
 + 
 + 
 +===== Querying for qualitative spatial relations ===== 
 + 
 +Using [[reason_using_computables|computables]] that calculate qualitative spatial relations between objects, we can query e.g. in which container we expect to find sausage1, ask for the content of Refrigerator67, or ask what is on top of Dishwasher37: 
 + 
 +<code prolog> 
 + ?- rdf_triple(knowrob:'in-ContGeneric', map_obj:sausage1, C). 
 + C = knowrob:'Refrigerator67'
    
- % all HandTools (e.g. silverware) + ?rdf_triple(knowrob:'in-ContGeneric', O, knowrob:'Refrigerator67'). 
- ?- owl_individual_of(A, knowrob:'HandTool'). + map_obj:'cheese1' ; 
- A = 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#knife1'+ map_obj:'milk1' ; 
- A = 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#fork1' + map_obj:'sausage1'
-  +
- % all FoodVessels (i.e. pieces of tableware) +
- ?- owl_individual_of(A, knowrob:'FoodVessel'). +
- 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#cup1' ; +
- = 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#plate1' ; +
- = 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#saucer1'+
    
- % everything with a handle: + ?rdf_triple(knowrob:'on-Physical'A, knowrob:'Dishwasher37'). 
- ?- owl_has(A, knowrob:properPhysicalPartsH), owl_individual_of(H knowrob:'Handle'). + A = map_obj:'cup1' ; 
- A = 'http://ias.cs.tum.edu/kb/knowrob.owl#Dishwasher37', + knowrob:'CounterTop205'
- = 'http://ias.cs.tum.edu/kb/knowrob.owl#Handle145'+
 </code> </code>
  
-===== Infer likely storage locations ===== 
  
-Apart from the current environment setup, robots sometimes need to reason about the nominal locations of objects, for example when cleaning up or when unpacking a shopping basket. There are different techniques for inferring the location where an object should be placed. +===== Inferring likely storage locations =====
  
-  * Using assertions of the [https://ias.cs.tum.edu/_media/spezial/bib/pancakes11humanoids.pdf storagePlaceFor] property is a rather genericthough not very adaptive technique that allows to state e.g. that perishable items belong into the refrigerator. It does not require any knowledge about the environment, but since it works on the level of object classesit cannot choose between containers of the same type, e.g. different cupboards. +For some tasksrobots need to reason about the nominal locations of objectsfor example when cleaning up or when unpacking a shopping basketThere are different techniques for inferring the location where an object should be placed
-  * A finer-grained solution is based on [https://ias.cs.tum.edu/people/tenorth/publications?key=schuster12orgprinciples organizational principles] that places objects at the location where semantically similar objects are stored. It requires some knowledge about the distribution of other objects in the environment.+
  
-=== Query for likely storage location ===+  * Using assertions of the [[http://knowrob.org/_media/bib/pancakes11humanoids.pdf|storagePlaceFor]] property is a rather generic, though not very adaptive technique that allows to state e.g. that perishable items belong into the refrigerator. It does not require any knowledge about the environment, but since it works on the level of object classes, it cannot choose between containers of the same type, e.g. different cupboards. 
 +  * A finer-grained solution is based on [[http://knowrob.org/_media/bib/schuster12orgprinciples.pdf|organizational principles]] that places objects at the location where semantically similar objects are stored. It requires some (partial) knowledge about the distribution of other objects in the environment. 
 + 
 + 
 +=== Querying for likely storage locations ===
  
 The simple option based on the storagePlaceFor predicate can be queried as follows in order to determine where an object (instance or class) shall be stored, or which known objects are to be stored in a given container: The simple option based on the storagePlaceFor predicate can be queried as follows in order to determine where an object (instance or class) shall be stored, or which known objects are to be stored in a given container:
-<code> +<code prolog
- ?- storagePlaceFor(Place, map_obj:'butter1'). +?- storagePlaceFor(Place, map_obj:'butter1'). 
- Place = 'http://ias.cs.tum.edu/kb/knowrob.owl#Refrigerator67'+Place = knowrob:'Refrigerator67'
  
- ?- storagePlaceFor(knowrob:'Refrigerator67', Obj). +?- storagePlaceFor(knowrob:'Refrigerator67', Obj). 
- Obj = 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#butter1'+Obj = map_obj:'butter1'
- Obj = 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#buttermilk1'+Obj = map_obj:'buttermilk1'
- Obj = 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#cheese1'+Obj = map_obj:'cheese1'
- Obj = 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#milk1'; +Obj = map_obj:'milk1'; 
- [...]+[...]
 </code> </code>
  
 An extension of the storagePlaceFor predicate also reads why the system came to the conclusion that something is to be stored at some place: An extension of the storagePlaceFor predicate also reads why the system came to the conclusion that something is to be stored at some place:
-<code>+<code prolog>
  ?- storagePlaceForBecause(Place, map_obj:'butter1', Because).  ?- storagePlaceForBecause(Place, map_obj:'butter1', Because).
- Place = 'http://ias.cs.tum.edu/kb/knowrob.owl#Refrigerator67', + Place = knowrob:'Refrigerator67', 
- Because = 'http://ias.cs.tum.edu/kb/knowrob.owl#Perishable'+ Because = knowrob:'Perishable'
 </code> </code>
  
 {{ :storage_place_example_pancake.png?900 |}} {{ :storage_place_example_pancake.png?900 |}}
  
-TODO: add orgprinciples calls+**TODO: add orgprinciples calls**
  
-=== Check for objects that are not at their storage location === 
  
-By combining the semantic map, giving the current object locations, with the knowledge about the locations where objects should be, the robot can determine which objects are mis-placed. This may for instance be useful when tidying up an environment.+=== Checking for objects that are not at their storage location ===
  
-The following code first compute which objects are inside which other ones, then selects those that are food or drink, computes their most likely storage place (which, in this example, is usually the refrigerator), and compares the two places. As a result, the system finds out that the butter and the buttermilk are misplaced in a drawer and in the oven, respectively.+By combining the semantic map and the current object locations with the knowledge about the locations where objects should be, the robot can determine which objects are misplaced. This may for instance be useful when tidying up an environment. The following code first compute which objects are inside which other ones, then selects those that are food or drink, computes their most likely storage place (which, in this example, is usually the refrigerator), and compares the two places. As a result, the system finds out that the butter and the buttermilk are misplaced in a drawer and in the oven, respectively.
  
-<code>+<code prolog>
  ?- rdf_triple(knowrob:'in-ContGeneric', Obj, ActualPlace),   ?- rdf_triple(knowrob:'in-ContGeneric', Obj, ActualPlace), 
     owl_individual_of(Obj, knowrob:'FoodOrDrink'),      owl_individual_of(Obj, knowrob:'FoodOrDrink'), 
     storagePlaceFor(StoragePlace,Obj),      storagePlaceFor(StoragePlace,Obj), 
     ActualPlace\=StoragePlace.     ActualPlace\=StoragePlace.
- Obj = 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#butter1', + Obj = map_obj:'butter1', 
- ActualPlace = 'http://ias.cs.tum.edu/kb/knowrob.owl#Drawer31', + ActualPlace = knowrob:'Drawer31', 
- StoragePlace = 'http://ias.cs.tum.edu/kb/knowrob.owl#Refrigerator67'+ StoragePlace = knowrob:'Refrigerator67'
- Obj = 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#buttermilk1', + Obj = map_obj:'buttermilk1', 
- ActualPlace = 'http://ias.cs.tum.edu/kb/knowrob.owl#Oven19', + ActualPlace = knowrob:'Oven19', 
- StoragePlace = 'http://ias.cs.tum.edu/kb/knowrob.owl#Refrigerator67'+ StoragePlace = knowrob:'Refrigerator67'
 </code> </code>
  
-===== Read object component hierarchy =====+You will notice that it takes a bit of time to answer the query: This is because the first predicate searches for all objects that are inside another one, and for doing this has to compute all pairwise 'inside' relations between all objects. By restricting the set of objects to be considered as inner and outer objects, this could be sped up a lot. This is one example of a general property of Prolog: The efficiency depends on how the query is formulated.
  
-Composed objects and their parts are linked by an inverse part-of hierarchy, described using the properPhysicalParts property in OWL. This property is transitive, i.e. a part of a part of an object is also a part of the object itself. You can read all parts and sub-parts of an object using owl_has, which takes the transitivity into account. In the example below, Handle160 is a part of Door70, which by itself is part of Refrigerator67. + 
-<code>+===== Reading the object component hierarchy ===== 
 + 
 +Composed objects and their parts are linked by a 'parts' hierarchy, described using the properPhysicalParts property in OWL. This property is transitive, i.e. a part of a part of an object is also a part of the object itself. You can read all parts and sub-parts of an object using owl_has, which takes the transitivity into account. In the example below, Handle160 is a part of Door70, which by itself is part of Refrigerator67. 
 +<code prolog>
  ?- owl_has(knowrob:'Refrigerator67', knowrob:properPhysicalParts, P).  ?- owl_has(knowrob:'Refrigerator67', knowrob:properPhysicalParts, P).
- P = 'http://ias.cs.tum.edu/kb/knowrob.owl#Door70'+ P = knowrob:'Door70'
- P = 'http://ias.cs.tum.edu/kb/knowrob.owl#Handle160'+ P = knowrob:'Handle160'
- P = 'http://ias.cs.tum.edu/kb/knowrob.owl#Hinge70'+ P = knowrob:'Hinge70'
 </code> </code>
  
-=== Special case: articulated objects like cupboards === 
  
-{{ :part-of-hierarchy-map.png?nolink&472| }}+===== Representation of articulated objects such as cupboards =====
  
-Articulated objects like cupboards that have doors or drawers are represented in a special way to describe, on the one hand, the component hierarchy, and on the other hand the fixed and moving connections. Like for other composed objects, there is a part-of hierarchy (properPhysicalParts). Joints are parts of the cupboard/parent object, and are fixed-to (connectedTo-Rigidly) both the parent and the child (e.g. the door). In addition, the child is hingedTo or prismaticallyConnectedTo the parent.+{{ :part-of-hierarchy-map.png?nolink&472| }}
  
 +Articulated objects, e.g. cupboards, that have doors or drawers are represented in a special way to describe, on the one hand, the component hierarchy, and, on the other hand, which connections are fixed and which are movable. Like for other composed objects, there is a part-of hierarchy (properPhysicalParts). Joints are parts of the cupboard/parent object, and are fixed-to (connectedTo-Rigidly) both the parent and the child (e.g. the door). In addition, the child is hingedTo or prismaticallyConnectedTo the parent.
  
 Joints are described using the following properties, which are compatible to the representation used by the [http://www.ros.org/wiki/articulation ROS articulation stack]. Joints are described using the following properties, which are compatible to the representation used by the [http://www.ros.org/wiki/articulation ROS articulation stack].
Line 153: Line 183:
  
  
-===== Read articulation information =====+===== Reading articulation information =====
  
-There are some convenience predicates for reading, creating, updating and deleting joints from articulated objects. This task is on the one hand rather common, on the other hand somewhat complex because the structure visualized in the previous image needs to be established. +There are some helper predicates for reading, creating, updating and deleting joints from articulated objects. This task is on the one hand rather common, on the other hand somewhat complex because the structure visualized in the previous image needs to be established. To create a joint of type knowrob:'HingedJoint' between two object instances roboearth:'IkeaExpedit2x40' and roboearth:'IkeaExpeditDoor13' at position (1,1,1) with unit orientation, radius 0.33m and joint limits 0.1 and 0.5 respectively, one can use the following statement: 
- +<code prolog>
-To create a joint of type knowrob:'HingedJoint' between two object instances roboearth:'IkeaExpedit2x40' and roboearth:'IkeaExpeditDoor13' at position (1,1,1) with unit orientation, radius 0.33m and joint limits 0.1 and 0.5 respectively, one can use the following statement: +
-<code>+
  create_joint_information('HingedJoint', roboearth:'IkeaExpedit2x40', roboearth:'IkeaExpeditDoor13',   create_joint_information('HingedJoint', roboearth:'IkeaExpedit2x40', roboearth:'IkeaExpeditDoor13', 
                            [1,0,0,1,0,1,0,1,0,0,1,1,0,0,0,1], [], '0.33', '0.1', '0.5', Joint).                            [1,0,0,1,0,1,0,1,0,0,1,1,0,0,0,1], [], '0.33', '0.1', '0.5', Joint).
 </code> </code>
  
-If a prismatic joint is to be created instead, the empty list [] needs to be replaced with a unit vector describing the joint's direction, e.g. [0,0,1] for a joint opening in z-direction, and the joint type needs to be set as 'PrismaticJoint'. +If a prismatic joint is to be created instead, the empty list [] needs to be replaced with a unit vector describing the joint's direction, e.g. [0,0,1] for a joint opening in z-direction, and the joint type needs to be set as 'PrismaticJoint'. Joint information can conveniently be read using the following predicate that requires a joint instance as argument: 
- +<code prolog>
-Joint information can conveniently be read using the following predicate that requires a joint instance as argument: +
-<code>+
  read_joint_information(Joint, Type, Parent, Child, Pose, Direction, Radius, Qmin, Qmax).  read_joint_information(Joint, Type, Parent, Child, Pose, Direction, Radius, Qmin, Qmax).
 </code> </code>
  
 To update joint information, one can use the following predicate: To update joint information, one can use the following predicate:
-<code>+<code prolog>
  update_joint_information(Joint, 'HingedJoint', [1,0,0,2,0,1,0,2,0,0,1,2,0,0,0,1], [1,2,3], 0.32, 1.2, 1.74).  update_joint_information(Joint, 'HingedJoint', [1,0,0,2,0,1,0,2,0,0,1,2,0,0,0,1], [1,2,3], 0.32, 1.2, 1.74).
 </code> </code>
  
-===== Read and convert units of measure ===== 
  
-All numerical values can optionally be annotated with a unit of measure. To keep the system backwards compatible, other values are interpreted to be given in the respective SI unit (e.g. meter, second). 
  
-Full article incl. explanation of design choices and links to further information: [[Measurement_units]] +===== Reading and converting units of measure =====
-<code> +
- $ roscd knowrob_common/owl +
- $ rosrun rosprolog rosprolog ias_knowledge_base +
-  +
- ?- owl_parse('knowrob_units.owl', false, false, true). +
- ?- consult('../prolog/knowrob_units.pl'). +
-  +
- % read information that is asserted for a test instance +
- ?- rdf_has('http://ias.cs.tum.edu/kb/knowrob_units.owl#test-inst', +
-            'http://ias.cs.tum.edu/kb/knowrob_units.owl#length', O). +
- literal(type('http://qudt.org/vocab/unit#Centimeter','12.0')) . +
-  +
- % manual conversion into other units +
- ?- convert_to_unit($O, 'http://qudt.org/vocab/unit#Kilometer', P). +
- 0.00012. +
-  +
- ?- convert_to_unit($O, 'http://qudt.org/vocab/unit#Meter', P). +
- 0.12. +
-  +
- ?- convert_to_unit($O, 'http://qudt.org/vocab/unit#Millimeter', P). +
- 120.0. +
-</code>+
  
-The integration with the rdf_triple computables allows to transparently convert values into the desired unit of measure:  +All numerical values in KnowRob can optionally be annotated with unit of measure. To keep the system backwards compatible,  values without annotation are interpreted to be given in the respective SI unit (e.gmetersecond). The full article including an explanation of the design choices and links to further information can be found [[/doc/measurement_units|here]].
-<code> +
- % transparent conversion during the query   +
- ?- rdf_triple('http://ias.cs.tum.edu/kb/knowrob_units.owl#length' +
-               'http://ias.cs.tum.edu/kb/knowrob_units.owl#test-inst',  +
-                literal(type('http://qudt.org/vocab/unit#Meter', Val))). +
- Val = 0.12 ; +
-  +
- ?- rdf_triple('http://ias.cs.tum.edu/kb/knowrob_units.owl#length',  +
-               'http://ias.cs.tum.edu/kb/knowrob_units.owl#test-inst',  +
-                literal(type('http://qudt.org/vocab/unit#Kilometer', Val))). +
- Val = 0.00012 ; +
-</code>+
  
- 
-===== Convert between relative and global coordinates ===== 
-see here for now: [[Coordinate_systems]] 
- 
-===== Query for qualitative spatial relations ===== 
- 
-Using [[reason_using_computables|computables]] that calculate qualitative spatial relations between objects, we can query e.g. in which container we expect to find sausage1, ask for the content of Refrigerator67, or ask what is on top of Dishwasher37: 
- 
-<code> 
- ?- rdf_triple(knowrob:'in-ContGeneric', map_obj:sausage1, C). 
- C = 'http://ias.cs.tum.edu/kb/knowrob.owl#Refrigerator67' 
-  
- ?- rdf_triple(knowrob:'in-ContGeneric', O, knowrob:'Refrigerator67'). 
- O = 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#cheese1' ; 
- O = 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#milk1' ; 
- O = 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#sausage1' 
-  
- rdf_triple(knowrob:'on-Physical', A, knowrob:'Dishwasher37'). 
- A = 'http://ias.cs.tum.edu/kb/ccrl2_map_objects.owl#cup1' ; 
- A = 'http://ias.cs.tum.edu/kb/knowrob.owl#CounterTop205' 
-</code>