1. Robot architectures
  2. Choosing an architecture
  3. Planning
  4. Building a planning system
  5. STRIPS-style planning
  6. Developing a plan
  7. The algorithm
  8. An example

Robot architectures

Previously we considered effectors and sensors (both in lecture and in lab).

Now we step back and look at the overall control mechanism.

The architecture of a robot defines how the job of generating actions from percepts is organized, i.e., how robot control is done.

A spectrum of robot control:

         Deliberative <-------------> Reactive
(Actions planned)                         (Reflexive)

Choosing an architecture

If our focus is on autonomous mobile robots in dynamic environments where: not immediately clear where we should be on the spectrum of robot control. So we'll consider both extremes.

Planning

An example of a task for which it might be useful for a robot to formulate a plan: Fill copy requests for the Computer Science (CS) Department It might not make sense to plan the lowest level details (i.e., every tiny motion of the robot). However, it might make sense to figure out the major steps and the order in which they should be performed.

Consider, for example, the way you plan your trips to Williams at the beginning of each academic year. Do you plan out all of your actual leg and arm motions? or do you plan at the level of "I need to get a flight. Oh, and I need to figure out how to get to the airport."

Here's one high level plan for the "copy request" task:

This is a fine plan, but perhaps it's too high level. Maybe more detail would be helpful. In order to get the copies, the robot first needs to bring the item to be copied to Office Services. And before doing that, the robot needs to pick up the item to be copied from the CS Department office.

A more detailed (but still high level) plan might look like this:


Building a planning system

Fundamentals of planning include:
  1. splitting problems into their subparts
  2. handling interactions among those subparts
In building a planning system (i.e., a program to do planning), we need to:

Choose operators: What is a fundamental unit of action? Is it something like

       "Go to CS office."
or is it something like
       "Move forward one inch."
Are we aiming for a high level plan? a very detailed plan? or do we want something in between? For example, might we want our plan for making copies to look like this: For each operator, specify pre- and post-conditions: That is, we need to specify what must be true about the world for the action to take place; we also need to specify how the world changes once the action has been performed.

To "cross route 2", for example, it might be a requirement that traffic be stopped. This is an example of a precondition.

Once the copy request has been picked up from the CS Department office, the robot holds the request, rather than the CS Department. This is an example of a postcondition.

Have a way for the robot to keep track of the state of its world. How does the robot know who currently holds the copy request, for example?

Have a method for determining the order in which actions should be organized. In general, you can't simply put actions (operators) together in random orders and expect them to work.


STRIPS-style planning

First we need to define operators (i.e., actions). Then for each one, we specify: The last two together make up a post-condition.

For example, say that we are building a planning system for a kitchen robot. This system might have the following operators, among others:

bake(cookieDough)
P:	preheated(oven) ^
        contains(pan, cookieDough)
A:	contains(pan, cookies)
D:	contains(pan, cookieDough)

preheat(oven)
P:	cool(oven)
A:	preheated(oven)
D:	cool(oven)

setuppan(cookieDough)
P:	contains(bowl, cookieDough) ^
        empty(pan)
A:	contains(pan, cookieDough)
D:	empty(pan) ^ contains(bowl, cookieDough)

mix(cookieDough)
P:	contains(bowl, cookieDoughIngredients)
A:	contains(bowl, cookieDough)
D:	contains(bowl, cookieDoughIngredients)

setupbowl(cookieDoughIngredients)
P:	oncounter(cookieDoughIngredients) ^ oncounter(bowl)
A:	contains(bowl, cookieDoughIngredients)
D:	oncounter(cookieDoughIngredients)

Next we need to define terms that will help us describe the state of the robot's world. These are: This vocabulary allows us to specify a goal state:
   contains(pan, cookies)
and a current state:
   oncounter(cookieDoughIngredients) ^
   oncounter(bowl) ^
   cool(oven) ^
   empty(pan)
Finally, we need a method for determining what to do and in what order.

Developing a plan

Planning problems tend to be tackled best as goal-directed search - i.e., going backward from the goal. So this is what we will do.

We will begin by asking ourselves how our current state is different from the goal state. We can then choose an operator (action) that would allow us to accomplish those things that are not currently true about the state of our world.

So, for example, going back to our xeroxing robot, the goal is to have copies. One way to achieve this is to have Office Services make them. But to have Office Services make copies, we need to pick up the request from the CS Department.

This method of reasoning is called means-ends analysis.


The algorithm

We will use a goal stack to develop a plan:

Here's the idea: Write your goal on a piece of paper. Find an operator to achieve that goal. Cross out your goal and instead list the action you need to perform.

Can you actually perform the action? If not, what has to be true about the state of the world to do so? Write down all the things you need to accomplish. List them ahead of the action that requires them.

The item on top of the list is the problem you want to focus on for now. Need to solve the problems at the top before you can get to the things on the bottom.

Let's write the algorithm a slightly different way, filling in some details:


An example.

Tracing through plan development for our kitchen robot will help to illustrate how the algorithm works.

The following are snapshots of a goal stack for our problem (annotated with explanatory material):


1)	contains(pan, cookies)
	
	this is the goal to solve.  If the goal is more complex, we solve
        each component individually.  If there is a part of the goal that
        is already true in the current state, we don't worry about it.

2)	bake(cookieDough)

	this is what you have to do to solve the goal

3)	preheated(oven) ^ contains(pan, cookieDough)
	bake(cookieDough)

	but you can't bake until you've preheated the oven and you have
	cookieDough in the pan

4)	preheated(oven)
        contains(pan, cookieDough)
	bake(cookieDough)

	split up the tasks to be accomplished before you can actually bake

5)	preheat(oven)
	contains(pan, cookieDough)
	bake(cookieDough)

	to achieve a preheated oven, you need to do the preheating

6)	cool(oven)
	preheat(oven)
	contains(pan, cookieDough)
	bake(cookieDough)

	you need to guarantee that the oven is cool before you do so.
	it is!  So the first action in the plan will be to preheat
        the oven.

        Update the description of the current state to reflect what
        would be true once the oven is preheated.  Developing the rest
        of the plan depends on this.

7)	contains(pan, cookieDough)
	bake(cookieDough)

	now you need to be sure that you have cookieDough in your pan

	current state is:
                preheated(oven)
                oncounter(cookieDoughIngredients)
                oncounter(bowl)
                empty(pan)

8)	setuppan(cookieDough)
	bake(cookieDough)

	to get cookieDough in the pan, you need to set it up

9)	contains(bowl, cookieDough) ^ empty(pan)
	setuppan(cookieDough)
	bake(cookieDough)

	to set it up, you need to have cookieDough in a bowl and an empty
	pan in which to put the dough.

10)	contains(bowl, cookieDough)
	setuppan(cookieDough)
	bake(cookieDough)

	make sure you take care of each of those things separately.
        Of course, if any are already set, then there's no reason
        to do them again.

11)	mix(cookieDough)
	setuppan(cookieDough)
	bake(cookieDough)

12)	contains(bowl, cookieDoughIngredients)
	mix(cookieDough)
	setuppan(cookieDough)
	bake(cookieDough)

	before you can have dough, you need to have ingredients in the bowl.

13)	setupbowl(cookieDoughIngredients)
	mix(cookieDough)
	setuppan(cookieDough)
	bake(cookieDough)

	to do that, you set up the bowl.

14)	oncounter(cookieDoughIngredients) ^ oncounter(bowl)
	setupbowl(cookieDoughIngredients)
	mix(cookieDough)
	setuppan(cookieDough)
	bake(cookieDough)

	which involves being sure that you have dough ingredients on the
        counter and a bowl on the counter as well.

	great!  you have that.  so go ahead and setupbowl with
	cookieDoughIngredients.  i.e., make that the second step
        in your plan.  Update the state to reflect what would be true
        once this action was done.

15)	mix(cookieDough)
	setuppan(cookieDough)
	bake(cookieDough)

	current state is: preheated(oven) ^
                          contains(bowl, cookieDoughIngredients) ^
			  oncounter(bowl) ^
			  empty(pan)
	
	now you can mix the dough and set up the pan.  i.e., those become
        the next two steps in the plan.

16)	bake(cookieDough)

	current state is: preheated(oven) ^
		          contains(pan, cookieDough) ^
	                  oncounter(bowl)

	there's nothing left to do except to go ahead and bake those cookies!

17)	empty stack

	current state is: preheated(oven) ^
                          contains(pan, cookies) ^
                          oncounter(bowl)

        And the plan is:
        preheat(oven)
        setupbowl(cookieDoughIngredients)
        mix(cookieDough)
        setuppan(cookieDough)
        bake(cookieDough)