Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| tutorials:intermediate:json_prolog [2019/04/24 11:17] – [Accessing data from Prolog] gkazhoya | tutorials:intermediate:json_prolog [2022/01/25 16:35] (current) – [Prerequisites] gkazhoya | ||
|---|---|---|---|
| Line 9: | Line 9: | ||
| This tutorial requires CRAM, roslisp_repl and ROS to have already been installed. Go through the previous tutorials and the installation page if you don't have CRAM installed yet. | This tutorial requires CRAM, roslisp_repl and ROS to have already been installed. Go through the previous tutorials and the installation page if you don't have CRAM installed yet. | ||
| Make sure you have **Java 8** and **Gradle 5.1** already installed. Otherwise you won't be able to build KnowRob. Other versions could work, but have not been tested yet, so use them at your own risk! | Make sure you have **Java 8** and **Gradle 5.1** already installed. Otherwise you won't be able to build KnowRob. Other versions could work, but have not been tested yet, so use them at your own risk! | ||
| - | |||
| === Installation === | === Installation === | ||
| Line 28: | Line 27: | ||
| === Launch === | === Launch === | ||
| - | In addition to a **roscore** and the **roslisp_repl** you need to launch **json_prolog** in a Terminal with the following command: | + | In addition to a **roscore** and the **roslisp_repl** you need to launch **json_prolog** in a Terminal with the following command: |
| + | <code bash> | ||
| + | $ roslaunch rosprolog rosprolog.launch | ||
| + | </ | ||
| + | or if you're using an older version of KnowRob, then the following command: | ||
| <code bash> | <code bash> | ||
| $ roslaunch json_prolog json_prolog.launch | $ roslaunch json_prolog json_prolog.launch | ||
| Line 66: | Line 69: | ||
| X being the variable we asked Prolog to fill with a value. Whenever Prolog returns a value for a variable, the variable name gets prefixed with a question mark. " | X being the variable we asked Prolog to fill with a value. Whenever Prolog returns a value for a variable, the variable name gets prefixed with a question mark. " | ||
| In a [[json_prolog# | In a [[json_prolog# | ||
| + | |||
| + | Why do we get ''? | ||
| + | What does the second bracket do? | ||
| + | Let's add another variable to the query -- the variable ''? | ||
| + | <code lisp> | ||
| + | CL-USER> (json-prolog: | ||
| + | </ | ||
| + | This binds ''? | ||
| + | The result of the query is | ||
| + | <code lisp> | ||
| + | (((?X . 1) (?Y . 1))) | ||
| + | </ | ||
| + | Therefore, the second bracket makes a list of bindings for each variable in the query: | ||
| + | <code lisp> | ||
| + | ((?X . 1) (?Y . 1)) | ||
| + | </ | ||
| + | is a list of bindings for variable ''? | ||
| + | |||
| + | The last outer bracket is explained next. | ||
| ==== prolog-simple ==== | ==== prolog-simple ==== | ||
| Line 77: | Line 99: | ||
| </ | </ | ||
| | | ||
| - | The result is basically still the same, but it looks a little bit more complex on the first glance. What we get is a list which contains two elements. The first one is a list in a list with two elements which we already know from the previous call with '' | + | The result is basically still the same, but it looks a little bit more complex on the first glance. What we get is a list which contains two elements. The first one is a list in a list with two elements which we already know from the previous call with '' |
| {1005F52FAB}> | {1005F52FAB}> | ||
| ==== lazy lists ==== | ==== lazy lists ==== | ||
| Line 95: | Line 117: | ||
| We save our list in a variable for convenience purposes. This allows us also to expand the so stored list, and we can see all the possible values Prolog found for the variable ''? | We save our list in a variable for convenience purposes. This allows us also to expand the so stored list, and we can see all the possible values Prolog found for the variable ''? | ||
| - | If we do the same with '' | + | Now we see why we need the outer bracket: the result of the query is a (lazy) list of all possible bindings for the query variables. Let us add another variable to the query again: |
| <code lisp> | <code lisp> | ||
| - | | + | CL-USER> (cut:force-ll (json-prolog: |
| - | (((?X . 1))) | + | (((?X . 1) (?Y . 1)) ((?X . 2) (?Y . 2)) ((?X . 3) (?Y . 3))) |
| - | CL-USER> (cut: | + | </ |
| - | (((?X . 1))) | + | We get a list of all possible bindings of the query variables, where the bindings is itself a list with one element for each variable. |
| + | |||
| + | If we evaluate our original '' | ||
| + | <code lisp> | ||
| + | CL-USER> (cut: | ||
| + | (((?X . 1)) ((?X . 2)) ((?X . 3))) | ||
| + | CL-USER> (cut: | ||
| + | (((?X . 1))) | ||
| </ | </ | ||
| Line 112: | Line 142: | ||
| Now that we have a lazy list with interesting information, | Now that we have a lazy list with interesting information, | ||
| | | ||
| - | We can use '' | + | We can use '' |
| - | <code lisp> | + | |
| - | CL-USER> (setq *our-list* | + | |
| - | | + | |
| - | (json-prolog: | + | |
| - | </ | + | |
| - | + | ||
| - | This gives us a (normal) list of bindings for the variables in the query. We only have one variable ''? | + | |
| <code lisp> | <code lisp> | ||
| + | CL-USER> (cut: | ||
| ((?X . 1)) | ((?X . 1)) | ||
| </ | </ | ||
| - | Now we can use '' | + | Same goes for '' |
| + | <code lisp> | ||
| + | CL-USER> (cut: | ||
| + | (((?X . 2)) | ||
| + | . # | ||
| + | :GENERATOR #< | ||
| + | | ||
| + | </ | ||
| + | |||
| + | When we have one element of the lazy list, we can use '' | ||
| <code lisp> | <code lisp> | ||
| - | | + | CL-USER> (cut: |
| - | | + | 1 |
| </ | </ | ||
| - | Gives us the result '' | + | Gives us the result '' |
| That way, one can extract the necessary information, | That way, one can extract the necessary information, | ||
| Line 142: | Line 175: | ||
| <code lisp> | <code lisp> | ||
| - | |||
| CL-USER> (json-prolog: | CL-USER> (json-prolog: | ||
| - | (NIL | + | (NIL) |
| - | . # | + | |
| - | : | + | |
| - | {1006444B3B}> | + | |
| - | | + | |
| </ | </ | ||
| + | |||
| + | In JSON Prolog '' | ||
| | | ||
| - | This allows us to use the **knowrob_common** package, which allows us to access many utility functions and also the most commonly used queries of KnowRob. | + | This allows us to use the '' |
| With this imported package we could now do the following: | With this imported package we could now do the following: | ||
| <code lisp> | <code lisp> | ||
| - | + | | |
| - | | + | (((?RESULT |
| - | (((|?Result| | + | |
| . # | . # | ||
| :GENERATOR #< | :GENERATOR #< | ||
| Line 164: | Line 193: | ||
| </ | </ | ||
| - | This query converts the first elements upper case letters into lower case, and stores the obtained result in the '' | + | This query converts the first elements upper case letters into lower case, and stores the obtained result in the '' |
| - | An overview of the currently available packages and their queries can be found [[http:// | + | An overview of the currently available packages and their queries can be found [[http:// |
| <code bash> | <code bash> | ||
| | | ||
| Line 175: | Line 204: | ||
| | | ||
| <code lisp> | <code lisp> | ||
| - | |||
| Prolog query failed: PrologException: | Prolog query failed: PrologException: | ||
| [Condition of type SIMPLE-ERROR] | [Condition of type SIMPLE-ERROR] | ||
| - | | ||
| </ | </ | ||
| | | ||
| - | and if you check your terminal, in which the **json_prolog** node is running, there will be a huge java print as well, basically explaining the same thing. | + | and if you check your terminal, in which the '' |
| | | ||
| - | | + | |
| - | ==== Some more information about Prolog in LISP ==== | + | ==== Case-sensitive variable names ==== |
| + | |||
| + | In the former query we got a weird result from Prolog which looked like this: | ||
| + | <code lisp> | ||
| + | |'' | ||
| + | </ | ||
| + | What do the pipes stand for in this case? | ||
| + | |||
| + | Lisp is case-insensitive, | ||
| + | |||
| + | <code lisp> | ||
| + | CL-USER> (eq 'hello ' | ||
| + | T | ||
| + | CL-USER> (eq 'hello ' | ||
| + | T | ||
| + | </ | ||
| + | |||
| + | Prolog, on the other hand, is case-sensitive. | ||
| + | And in some cases, one would like to have a case-sensitive variable in Lisp as well. | ||
| + | This is where the pipes come into play: | ||
| + | <code lisp> | ||
| + | CL-USER> (intern " | ||
| + | HELLO | ||
| + | :INTERNAL | ||
| + | CL-USER> (intern " | ||
| + | |Hello| | ||
| + | NIL | ||
| + | </ | ||
| + | The function '' | ||
| + | If the string is all capital, we get a normal usual symbol, in the other case we get the pipes. | ||
| + | |||
| + | The same is with Prolog, if your variable or any other symbol is not all caps, you will get a symbol in Lisp which has pipes around it: | ||
| + | |||
| + | <code lisp> | ||
| + | CL-USER> (json-prolog: | ||
| + | (((?X . 1))) | ||
| + | CL-USER> (json-prolog: | ||
| + | (((?MYVAR . 1))) | ||
| + | CL-USER> (json-prolog: | ||
| + | (((?MY_VAR . 1))) | ||
| + | CL-USER> (json-prolog: | ||
| + | (((|? | ||
| + | </ | ||
| + | |||
| + | In that case, to get the value of the variable you should also use pipes: | ||
| + | |||
| + | <code lisp> | ||
| + | CL-USER> (cut: | ||
| + | (car (json-prolog: | ||
| + | 1 | ||
| + | </ | ||
| + | |||
| + | Please note that in Prolog, all variables have to start with a capital letter and cannot contain dashes: | ||
| + | <code lisp> | ||
| + | CL-USER> (json-prolog: | ||
| + | NIL | ||
| + | CL-USER> (json-prolog: | ||
| + | NIL | ||
| + | </ | ||
| + | ==== (NIL) vs NIL ==== | ||
| | | ||
| If we want to check, if a certain number is member of the list, we must declare the variable accordingly. e.g. | If we want to check, if a certain number is member of the list, we must declare the variable accordingly. e.g. | ||

