Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
tutorials:advanced:bullet_world [2017/09/15 16:00] – [Geometric reasoning] gkazhoya | tutorials:advanced:bullet_world [2018/04/04 09:22] (current) – gkazhoya | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | //Tested with Cram branch: Cram4, ROS version: Indigo, Ubuntu 14.04// | ||
- | |||
====== Bullet world demonstration ====== | ====== Bullet world demonstration ====== | ||
- | This tutorial demonstrates how the internal belief state of the robot is represented in CRAM, how to update the world, how to perform specialized reasoning in it and how to use lightweight simulation for quick testing of plans. | + | This page migrated |
- | + | ||
- | This tutorial assumes that you have a basic understanding of how the belief state is implemented internally. You can read about this in the [[doc: | + | |
- | + | ||
- | ==== Installing the projection project ==== | + | |
- | + | ||
- | As the system we will be working with will get quite complex things might not go as expected. If you get into trouble while following this tutorial feel free to consult the [[: | + | |
- | + | ||
- | If you followed the installation instructions for the full CRAM on the Installation | + | |
- | + | ||
- | < | + | |
- | For the full installation of the environment you need Knowrob, CRAM reasoning and bullet physics, Roslisp and the cram_bullet_world_tutorial project. For the installation of Knowrob we recommend | + | |
- | + | ||
- | All the other dependencies you can get from {{:tutorials:advanced:projections.rosinstall.txt|this rosinstall file}}. Open up a terminal and '' | + | |
- | + | ||
- | <code bash>$ wstool init</ | + | |
- | + | ||
- | to create a fresh rosinstall file. (If '' | + | |
- | <code bash>$ wstool update</ | + | |
- | Right now you have all the sources you need, but before you build them we want to exclude some that we don't absolutely need, since they would cause you to install even more dependencies. For that you have to create a file named '' | + | |
- | <code bash> | + | |
- | touch cram_tutorials/ | + | |
- | touch cram_tutorials/ | + | |
- | touch cram_common/ | + | |
- | touch cram_pr2/ | + | |
- | touch cram_pr2/ | + | |
- | touch cram_pr2/ | + | |
- | touch cram_pr2/ | + | |
- | touch cram_pr2/ | + | |
- | touch cram_pr2/ | + | |
- | touch cram_projection_demos/ | + | |
- | </ | + | |
- | Having done that you can now build the system. | + | |
- | <code bash>$ cd .. | + | |
- | $ catkin_make</ | + | |
- | Source the workspace when the build is ready. | + | |
- | + | ||
- | --></ | + | |
- | ==== Environment setup ==== | + | |
- | + | ||
- | In order to be able to demonstrate many different features of the belief state representation we will set up the environment of the robot similar to how it is done for the real system: we will need an occupancy map for navigation, an IK solver for manipulation, | + | |
- | + | ||
- | First, let's set up the environment in our terminal by calling the launch file. It already brings up a '' | + | |
- | <code bash> | + | |
- | $ roslaunch cram_bullet_world_tutorial world.launch | + | |
- | </ | + | |
- | Let's look into that launchfile. | + | |
- | <code bash> | + | |
- | $ roscd cram_bullet_world_tutorial | + | |
- | $ cat launch/ | + | |
- | </ | + | |
- | The occupancy map is for navigating the robot around furniture. The kitchens URDF represents it as if the kitchen were an actual robot whose state can change. Its joint states indicate specific points in the kitchen, which change if we, for example, open a drawer. Mainly, the joint states are for visualisation of important places of the kitchen in rviz (see the picture in section '' | + | |
- | To check if the kitchen URDF was uploaded to the ROS parameter server we can execute the following: | + | |
- | <code bash> | + | |
- | $ rosparam get / | + | |
- | </ | + | |
- | + | ||
- | Besides all the kitchen information also the PR2 URDF is loaded: | + | |
- | <code bash> | + | |
- | $ rosparam get / | + | |
- | </ | + | |
- | To simulate simple grasping tasks with the PR2 robot in the bullet-world we need an inverse kinematics solver for the arms. In the launch file those are the '' | + | |
- | + | ||
- | If you retrieve data from the '' | + | |
- | + | ||
- | ====REPL setup==== | + | |
- | + | ||
- | Now, let's load the package in the REPL: | + | |
- | <code lisp> | + | |
- | CL-USER> (ros-load: | + | |
- | CL-USER> (in-package : | + | |
- | </ | + | |
- | + | ||
- | As we will be talking to the ROS master, let's first start a node: | + | |
- | <code lisp> | + | |
- | BTW-TUT> (roslisp: | + | |
- | </ | + | |
- | + | ||
- | First, let's do all the initializations: | + | |
- | < | + | |
- | <code lisp> | + | |
- | BTW-TUT> (cram-occupancy-grid-costmap:: | + | |
- | BTW-TUT> (cram-bullet-reasoning-belief-state:: | + | |
- | BTW-TUT> (cram-location-costmap:: | + | |
- | BTW-TUT> (cram-tf:: | + | |
- | </ | + | |
- | + | ||
- | The functions above initialize and clean up the environment of the REPL. | + | |
- | Currently, we call those functions per hand for educational purposes. | + | |
- | However, there exists a function that does the initialization automatically and spawns the completely set up visualization window. It will be described later. | + | |
- | + | ||
- | The way CRAM is designed is that the belief state (the Bullet world) is only updated through Prolog queries, as we consider the belief state to be "robot knowledge" | + | |
- | + | ||
- | A new Bullet world instance is created when we load the '' | + | |
- | + | ||
- | <code lisp> | + | |
- | BTW-TUT> (prolog: | + | |
- | </ | + | |
- | + | ||
- | ==== Bullet world initialization ==== | + | |
- | + | ||
- | To be able to see what is going on in the belief state and to ease the debugging process we visualize the current world instance with OpenGL: | + | |
- | <code lisp> | + | |
- | BTW-TUT> (prolog: | + | |
- | (btr: | + | |
- | </ | + | |
- | Please note, that the visualization window does not necessarily need to be open when the robot is operating and using its belief state, in fact, it should be closed to save processing power. | + | |
- | + | ||
- | The " | + | |
- | + | ||
- | The first thing we need is the floor plane: | + | |
- | <code lisp> | + | |
- | BTW-TUT> (prolog: | + | |
- | (assert (btr:object ?world : | + | |
- | :normal (0 0 1) :constant 0)))) | + | |
- | </ | + | |
- | This '' | + | |
- | <code lisp> | + | |
- | BTW-TUT> Alt-x | + | |
- | rgrep RET | + | |
- | (<- (assert RET | + | |
- | *.lisp RET | + | |
- | / | + | |
- | </ | + | |
- | There are quite a few definitions here, serving various queries. All of them have in common, that they **change** something in the world. The one we are reaching by the previous call is this one, located in '' | + | |
- | <code lisp> | + | |
- | (<- (assert (object ?world ? | + | |
- | (assert ?world (object ? | + | |
- | </ | + | |
- | + | ||
- | In the assert query, the '': | + | |
- | + | ||
- | Via the launch file at the beginning of this tutorial the robot URDF representation has been uploaded to the ROS parameter server under the name '' | + | |
- | <code lisp> | + | |
- | BTW-TUT> (let ((robot-urdf | + | |
- | | + | |
- | (roslisp: | + | |
- | | + | |
- | `(and (btr: | + | |
- | (cram-robot-interfaces: | + | |
- | (assert (btr:object ?world :urdf ?robot ((0 0 0) (0 0 0 1)) :urdf , | + | |
- | (cram-robot-interfaces: | + | |
- | (assert (btr: | + | |
- | (assert (btr: | + | |
- | </ | + | |
- | + | ||
- | The line '' | + | |
- | '' | + | |
- | '' | + | |
- | This line: | + | |
- | <code lisp> | + | |
- | (assert (btr:object ?world :urdf ?robot ((0 0 0) (0 0 0 1)) :urdf , | + | |
- | </ | + | |
- | spawns the robot. | + | |
- | Keep in mind, that spawning a robot in the world creates a new object. The first '': | + | |
- | Then we read out the hard-coded values for robot arm parking states, where the arms are not in the way, and assert those joint states to our PR2 object of the Bullet world. | + | |
- | + | ||
- | Finally, let's spawn the kitchen environment (it will take some time as we query KnowRob for the semantic environment map): | + | |
- | <code lisp> | + | |
- | BTW-TUT> (let ((kitchen-urdf | + | |
- | | + | |
- | (roslisp: | + | |
- | | + | |
- | `(and (btr: | + | |
- | (assert (btr:object ?world : | + | |
- | :urdf , | + | |
- | </ | + | |
- | In the visualization window you can now see the kitchen loaded from the URDF with the semantic map information attached to it. If you want to have only a visualization of the semantic map without using the URDF, you just need to skip passing the URDF parameter: '' | + | |
- | + | ||
- | You can see the semantic map in rviz as well. Open up a terminal and type ''" | + | |
- | + | ||
- | {{: | + | |
- | + | ||
- | If there are parameters missing (left box) you can add them using the ' | + | |
- | + | ||
- | {{: | + | |
- | + | ||
- | To see the URDF of the kitchen in RViz you need its description name ' | + | |
- | + | ||
- | When you are ready with the robot model, look at the ' | + | |
- | + | ||
- | As you can see, this environment visualizes all the TF poses we can use in our tutorial. Get back to the debug window (Bullet visualization window) to see the actual meshes of the objects. The debug window only shows the collision meshes, not the detailed visuals, since we want to keep the bullet world fast and lightweight and concentrate on collisions not visuals. | + | |
- | + | ||
- | The environment is now initialized. For convenience, | + | |
- | If you call it now it will reinitialize everything, which is also fine: | + | |
- | + | ||
- | <code lisp> | + | |
- | BTW-TUT> (roslisp-utilities: | + | |
- | </ | + | |
- | + | ||
- | This starts a ROS node and executes the ROS initialization functions, which are registered in CRAM through '' | + | |
- | <code lisp> | + | |
- | BTW-TUT> (alexandria: | + | |
- | </ | + | |
- | You should find all of the functions that we manually called above and one additional, the '' | + | |
- | + | ||
- | + | ||
- | ==== Manipulating the kitchen ==== | + | |
- | + | ||
- | Make sure you have spawned your kitchen from urdf, not the semantic map. Check the section above for spawning the kitchen. Let us inspect the kitchen now: | + | |
- | + | ||
- | <code lisp> | + | |
- | BTW-TUT> (btr:object btr: | + | |
- | </ | + | |
- | + | ||
- | If needed, change the name of ': | + | |
- | + | ||
- | <code lisp> | + | |
- | BTW-TUT> | + | |
- | (btr: | + | |
- | ' | + | |
- | | + | |
- | </ | + | |
- | + | ||
- | If you did everything right, the fridge door should now be slightly open. Check the other joints and change them as you wish. Watch their limits though. | + | |
- | + | ||
- | ==== Spawn and change objects in the world ==== | + | |
- | + | ||
- | From this point on let us use the fast initialization function to start the bullet-world: | + | |
- | + | ||
- | <code lisp> | + | |
- | BTW-TUT> (roslisp-utilities: | + | |
- | </ | + | |
- | + | ||
- | + | ||
- | Now let us spawn some household objects: | + | |
- | <code lisp> | + | |
- | BTW-TUT> | + | |
- | (prolog: | + | |
- | | + | |
- | :mass 0.2 :color (1 0 0) :mesh :mug)))) | + | |
- | </ | + | |
- | There appears a mug above the robot' | + | |
- | + | ||
- | <code lisp> | + | |
- | BTW-TUT> (prolog: | + | |
- | (assert (btr: | + | |
- | </ | + | |
- | Now the mug is above the kitchen island table. | + | |
- | + | ||
- | To get the instance of the spawned Bullet object there is a function '' | + | |
- | <code lisp> | + | |
- | BTW-TUT> (btr:object btr: | + | |
- | </ | + | |
- | We can get the pose of that object through the function '' | + | |
- | <code lisp> | + | |
- | BTW-TUT> (btr:pose (btr:object btr: | + | |
- | #< | + | |
- | #< | + | |
- | #< | + | |
- | </ | + | |
- | + | ||
- | ==== Geometric reasoning ==== | + | |
- | + | ||
- | Our mug is floating in the air. The belief state world in CRAM is static, in order to apply the physics to it we use the Bullet physics engine to simulate the world for a certain amount of time. | + | |
- | <code lisp> | + | |
- | BTW-TUT> (prolog: | + | |
- | (btr: | + | |
- | </ | + | |
- | This simulates the world for 1 second and the mug falls onto the table. | + | |
- | + | ||
- | We can also ask if the scene is stable or, if we simulate the world for longer time, would objects change positions: | + | |
- | <code lisp> | + | |
- | BTW-TUT> (prolog: | + | |
- | (btr:stable ?world))) | + | |
- | (((?WORLD . ...))) | + | |
- | </ | + | |
- | This copies our current world and simulates it for a certain amount of time and compares the poses of objects before and after | + | |
- | simulation. If the result we got is '' | + | |
- | + | ||
- | Now, let's ask if the mug is currently visible for the robot: | + | |
- | <code lisp> | + | |
- | BTW-TUT> (prolog: | + | |
- | (cram-robot-interfaces: | + | |
- | (btr: | + | |
- | NIL | + | |
- | </ | + | |
- | + | ||
- | Let's move PR2 such that the cup is in its visibility range: | + | |
- | <code lisp> | + | |
- | BTW-TUT> (prolog: | + | |
- | (assert (btr: | + | |
- | ((0.5 1 0) (0 0 1 )))))) | + | |
- | </ | + | |
- | and ask the visibility query again: instead of typing, put the cursor where you would type and press '' | + | |
- | + | ||
- | ==== Abstract entity descriptions ==== | + | |
- | + | ||
- | Now let's generate a distribution of locations from which the robot would be able to see the mug. For that we create an abstract location description that we call a // | + | |
- | <code lisp> | + | |
- | BTW-TUT> (let* ((mug-pose (btr:pose (btr:object btr: | + | |
- | (mug-pose-stamped (cl-transforms-stamped: | + | |
- | (mug-pose-designator (desig: | + | |
- | (to-see-designator (desig: | + | |
- | (:location , | + | |
- | | + | |
- | #< | + | |
- | | + | |
- | #< | + | |
- | #< | + | |
- | </ | + | |
- | + | ||
- | We create two symbolic descriptions: | + | |
- | + | ||
- | We can also completely abstract away from geometric poses (we used the '' | + | |
- | + | ||
- | <code lisp> | + | |
- | BTW-TUT> | + | |
- | (let* ((on-counter (desig: | + | |
- | (:name " | + | |
- | | + | |
- | (:at , | + | |
- | | + | |
- | (:object , | + | |
- | (desig: | + | |
- | #< | + | |
- | | + | |
- | #< | + | |
- | #< | + | |
- | </ | + | |
- | + | ||
- | Here, as we didn't specifically say which pose we are trying to perceive the robot randomly samples one pose from all the poses on the kitchen island table and generates a distribution to perceive that pose, i.e., it looks in the general direction of the table. If you look at the debug window now you can see a gaussian area near the table. We can use that pose to move the robot there. | + | |
- | + | ||
- | <code lisp> | + | |
- | BTW-TUT> (btr-utils: | + | |
- | </ | + | |
- | {{: | + | |
- | + | ||
- | ==== Grasp objects ==== | + | |
- | + | ||
- | We need a clean environment for this, so restart the demo with | + | |
- | <code lisp> | + | |
- | BTW-TUT> (roslisp-utilities: | + | |
- | </ | + | |
- | Now we need an object to grasp. For that we will use our own mesh of a bottle loaded from resources. | + | |
- | <code lisp> | + | |
- | BTW-TUT> (add-objects-to-mesh-list) | + | |
- | </ | + | |
- | Then we spawn an object of type bottle and move it onto the table. | + | |
- | <code lisp> | + | |
- | BTW-TUT> (btr-utils: | + | |
- | BTW-TUT> (btr-utils: | + | |
- | (cl-transforms: | + | |
- | (cl-transforms: | + | |
- | </ | + | |
- | Lastly we simulate the world for 100 seconds to make sure, nothing moves unexpectedly on runtime. | + | |
- | <code lisp> | + | |
- | BTW-TUT> (btr: | + | |
- | </ | + | |
- | From now on it's okay to move the robot. Before we grasp the bottle however we have to prepare the PR2, nothing fancy, just three steps: move the arms out of sight, navigate the base in front of the bottle and look at the bottle. The point we want the base to navigate to can be hard coded and saved temporarily. | + | |
- | <code lisp> | + | |
- | BTW-TUT> (setf ? | + | |
- | (cl-transforms-stamped: | + | |
- | " | + | |
- | 0.0 | + | |
- | | + | |
- | | + | |
- | </ | + | |
- | The same thing can be done with the point, we want to look at. | + | |
- | <code lisp> | + | |
- | BTW-TUT> (setf ? | + | |
- | (cl-transforms-stamped: | + | |
- | " | + | |
- | 0.0 | + | |
- | | + | |
- | | + | |
- | </ | + | |
- | As usual we need a top-level context to start the execution of cram plans. Besides that we also use a macro to determine, that the demo should be executed in simulation, not on the real robot. Putting that together we end up with this plan: | + | |
- | <code lisp> | + | |
- | BTW-TUT> | + | |
- | (proj: | + | |
- | (cpl: | + | |
- | (cpl:par | + | |
- | (pr2-pp-plans:: | + | |
- | (exe: | + | |
- | (type going) | + | |
- | (target (desig:a location (pose ? | + | |
- | (exe: | + | |
- | (type looking) | + | |
- | (target (desig:a location (pose ? | + | |
- | </ | + | |
- | We actually can execute the arm movement, navigation and head tilt in parallel, since each of them uses different joints of the robot. That's what '' | + | |
- | + | ||
- | With the torso so far down we won't be able to reach for the bottle, so we need to push him up. To grasp the bottle we also need its pose in the room. Therefore we first get the estimated position of the bottle, then perceive it for a more accurate pose. With that pose we start the plan '' | + | |
- | <code lisp> | + | |
- | BTW-TUT> | + | |
- | (proj: | + | |
- | (cpl: | + | |
- | (let* ((? | + | |
- | (type bottle))) | + | |
- | | + | |
- | (exe: | + | |
- | | + | |
- | (pr2-pp-plans:: | + | |
- | </ | + | |
- | + | ||
- | + | ||
- | Now the PR2 should have the bottle in his right gripper. | + | |
- | {{: | + | |
- | + | ||
- | Let's take a quick look into the '' | + | |
- | <code lisp> | + | |
- | BTW-TUT> | + | |
- | (defun drive-and-pick-up-plan (? | + | |
- | ;; navigate to a better pose | + | |
- | (drive-towards-object-plan ? | + | |
- | (cpl:par | + | |
- | (exe: | + | |
- | (type looking-at) | + | |
- | | + | |
- | (exe: | + | |
- | (type picking-up) | + | |
- | (arm ?arm) | + | |
- | | + | |
- | </ | + | |
- | Here he first calls a function to get the base in a position optimized for grasping with a specific arm. After that he again looks at the object and finally picks it up. To see which action designator is used for picking up the object we need a good search. Use ''" | + | |
- | + | ||
- | ==== Place objects ==== | + | |
- | + | ||
- | To place things held in the gripper we first need an object attached to a gripper. Use the previous chapter '' | + | |
- | <code lisp> | + | |
- | BTW-TUT> | + | |
- | (proj: | + | |
- | | + | |
- | | + | |
- | (type placing) | + | |
- | (arm right))))) | + | |
- | </ | + | |
- | + | ||
- | But if we want to place the bottle somewhere else we need to define those locations. Use hard-coded poses for now, since dynamic plans require massive failure handling, which will be discussed in a later chapter. Pick up the bottle again. | + | |
- | <code lisp> | + | |
- | BTW-TUT> | + | |
- | (proj: | + | |
- | | + | |
- | (let* ((? | + | |
- | (type bottle))) | + | |
- | (? | + | |
- | | + | |
- | </ | + | |
- | Now move the robot to the other table. We use a motion designator for that, who needs a specific pose. | + | |
- | <code lisp> | + | |
- | BTW-TUT> (proj: | + | |
- | | + | |
- | | + | |
- | (let ((?pose (cl-tf: | + | |
- | cram-tf: | + | |
- | (cl-transforms: | + | |
- | (cl-transforms: | + | |
- | (desig:a motion (type going) (target (desig:a location (pose ? | + | |
- | </ | + | |
- | This seems like a good spot to place the bottle. Let's put it down to coordinates -0.7 2.0 0.861667. | + | |
- | <code lisp> | + | |
- | BTW-TUT> (proj: | + | |
- | | + | |
- | (let ((? | + | |
- | " | + | |
- | (cl-transforms: | + | |
- | (cl-transforms: | + | |
- | | + | |
- | (type placing) | + | |
- | (arm right) | + | |
- | (target (desig:a location (pose ? | + | |
- | </ | + | |
- | With these actions you can pick up objects, move the robot and place them at specific points. The scene should now look like this: | + | |
- | + | ||
- | {{: | + | |
- | + | ||
- | ==== Construct plans ==== | + | |
- | + | ||
- | The goal of this chapter is to write a plan, that switches the position of two objects in the world. First we want to have a clean environment: | + | |
- | <code lisp> | + | |
- | BTW-TUT> (init-projection) | + | |
- | </ | + | |
- | If you just started your EMACS or loaded the package don't forget to add our extra meshes from resource, otherwise you won't be able to spawn a bottle. | + | |
- | <code lisp> | + | |
- | BTW-TUT> (add-objects-to-mesh-list) | + | |
- | </ | + | |
- | Now we need those two objects in the world. | + | |
- | <code lisp> | + | |
- | BTW-TUT> (prolog: | + | |
- | (assert (btr:object ?world :mesh bottle-1 ((-2 -0.9 0.861667d0) (0 0 0 1)) | + | |
- | :mass 0.2 :color (1 0 0) :mesh :bottle)) | + | |
- | (assert (btr:object ?world :mesh bottle-2 ((-0.65 2 0.955) (0 0 0 1)) | + | |
- | :mass 0.2 :color (0 1 0) :mesh :bottle)) | + | |
- | (btr: | + | |
- | </ | + | |
- | To make the plan shorter we can define some parameters a prior. The *pose-meal-table* is the pose, where the pr2 should stand, when he approaches the green bottle. The other pose, *pose-meal-counter* is the base pose for the counter table, when we want to place the bottle. | + | |
- | <code lisp> | + | |
- | BTW-TUT> | + | |
- | (defparameter *pose-bottle-1* | + | |
- | (cl-transforms-stamped: | + | |
- | " | + | |
- | | + | |
- | | + | |
- | + | ||
- | (defparameter *pose-bottle-2* | + | |
- | (cl-transforms-stamped: | + | |
- | " | + | |
- | | + | |
- | | + | |
- | + | ||
- | (defparameter *pose-meal-table* | + | |
- | (cl-tf: | + | |
- | " | + | |
- | | + | |
- | | + | |
- | + | ||
- | (defparameter *pose-counter* | + | |
- | (cl-transforms-stamped: | + | |
- | " | + | |
- | | + | |
- | | + | |
- | </ | + | |
- | Now we define the whole procedure. We go to the counter and pick up the first bottle. Then go to the meal table, pick up the other bottle and place the first bottle on the same spot. After that we go back to the counter and place the second bottle. You should define each of the small steps as separate functions, so your top-level plan stays readable. | + | |
- | <code lisp> | + | |
- | (defun spawn-two-bottles () | + | |
- | (unless (assoc :bottle btr:: | + | |
- | (add-objects-to-mesh-list)) | + | |
- | (prolog: | + | |
- | (assert (btr:object ?world :mesh bottle-1 ((-2 -0.9 0.861667d0) (0 0 0 1)) | + | |
- | :mass 0.2 :color (1 0 0) :mesh :bottle)) | + | |
- | (assert (btr:object ?world :mesh bottle-2 ((-0.65 2 0.955) (0 0 0 1)) | + | |
- | :mass 0.2 :color (0 1 0) :mesh :bottle)) | + | |
- | (btr: | + | |
- | + | ||
- | (defun move-arm-out-of-sight (&key (arm ' | + | |
- | (unless (listp arm) | + | |
- | (setf arm (list arm))) | + | |
- | (exe: | + | |
- | (let ((? | + | |
- | | + | |
- | | + | |
- | (type moving-joints) | + | |
- | (left-configuration ? | + | |
- | (right-configuration ? | + | |
- | + | ||
- | (defun navigate-to (? | + | |
- | (exe: | + | |
- | (type going) | + | |
- | (target (desig:a location (pose ? | + | |
- | + | ||
- | (defun look-at (? | + | |
- | (exe: | + | |
- | (type looking) | + | |
- | (target (desig:a location (pose ? | + | |
- | + | ||
- | (defun get-perceived-bottle-desig () | + | |
- | (let* ((? | + | |
- | (type bottle))) | + | |
- | | + | |
- | | + | |
- | (type detecting) | + | |
- | (object ? | + | |
- | ? | + | |
- | + | ||
- | (defun pick-up (? | + | |
- | (exe: | + | |
- | (type picking-up) | + | |
- | (arm ?arm) | + | |
- | | + | |
- | + | ||
- | (defun place-down (?pose ?arm) | + | |
- | (exe: | + | |
- | (type placing) | + | |
- | (arm ?arm) | + | |
- | | + | |
- | + | ||
- | (defun move-to-reach (? | + | |
- | (pr2-pp-plans:: | + | |
- | </ | + | |
- | Here we go. Now we can use those functions to write down the top-level plan. | + | |
- | <code lisp> | + | |
- | BTW-TUT> | + | |
- | (defun test-switch-two-bottles () | + | |
- | (spawn-two-bottles) | + | |
- | (proj: | + | |
- | (cpl: | + | |
- | ;; Go to counter top and perceive bottle | + | |
- | (let ((? | + | |
- | (?ptu-goal pr2-pp-plans:: | + | |
- | (cpl:par | + | |
- | ;; Move torso up | + | |
- | (exe: | + | |
- | | + | |
- | (move-arm-out-of-sight) | + | |
- | (navigate-to ? | + | |
- | (look-at ? | + | |
- | ;; Pick up bottle-1 with right arm. | + | |
- | (let* ((? | + | |
- | (move-to-reach ? | + | |
- | (pick-up ? | + | |
- | ;; (move-arm-out-of-sight :arm :right) | + | |
- | ;; Move to the meal table | + | |
- | (let ((?pose *pose-meal-table*)) | + | |
- | (navigate-to ?pose)) | + | |
- | ;; Pick up bottle-2 with left arm | + | |
- | (let* ((? | + | |
- | (move-to-reach ? | + | |
- | (pick-up ? | + | |
- | ;; Move left arm out of sight | + | |
- | (move-arm-out-of-sight :arm :left) | + | |
- | ;; Place bottle-1 on second table | + | |
- | (let ((? | + | |
- | (place-down ?drop-pose :right)) | + | |
- | ;; Move right arm out of sight | + | |
- | (move-arm-out-of-sight :arm :right) | + | |
- | ;; Move to the counter table | + | |
- | (let ((? | + | |
- | | + | |
- | ;; Place bottle-2 on the counter | + | |
- | (let ((? | + | |
- | (place-down ?drop-pose :left)) | + | |
- | (move-arm-out-of-sight)))) | + | |
- | </ | + | |
- | Each time you run '' | + | |
- | + | ||
- | + | ||
- | < | + | |
- | ==== Light-weight simulation (projection of plans) ==== | + | |
- | + | ||
- | Now, let's use light-weight simulation to try to find our particular red mug: | + | |
- | <code lisp> | + | |
- | DEMO> | + | |
- | (with-projection-environment pr2-bullet-projection-environment | + | |
- | (top-level | + | |
- | (with-designators | + | |
- | ((on-counter :location `((:on " | + | |
- | | + | |
- | | + | |
- | (:at , | + | |
- | (reference on-counter) | + | |
- | (format t " | + | |
- | (let ((perceived-object (perceive-object 'a an-object))) | + | |
- | (unless (desig-equal an-object perceived-object) | + | |
- | (equate an-object perceived-object)) | + | |
- | an-object)))) | + | |
- | </ | + | |
- | We execute our plan in a projection environment which substitutes the real robot controllers and sensors with their simplified models. Next, we define our object that we are searching for in a symbolic abstract way. After that, we execute the '' | + | |
- | + | ||
- | + | ||
- | To see an execution of a complete pick and place plan try the following: | + | |
- | <code lisp> | + | |
- | DEMO> (start-ros-and-bullet) | + | |
- | (execute-demo : | + | |
- | </ | + | |
- | This will execute the plan from the pancake making demo. The code can be found in the '' | + | |
- | --> </ | + | |
- | ---- | + | |
- | + | ||
- | + | ||
- | The package '' | + | |
- | By pressing '' | + |