Rocket Landing Simulator

Gate Check #4 - Artificial Intelligence
Go Back to the Assignment Description

Part 1 (Overview) - Part 2 (Getting Ready) - Part 3 (AI Logic Part I) - Part 4 (AI Logic Part II) - Part 5 (AI Training)

Let's Build an AI (Part II)

NOTE: In this section, we show you how to build a rules-based agent (i.e., an expert system) that should be able to land on the boat "most of the time." We highly encourage you to use our logic design as a starting point. You can then deviate in order to make your final AI as intelligent/efficient as you like.

Now that our run_autopilot() is being called, we need to add the logic that will let our AI decide when to fire the rocket's thrusters.

So . . . yeah . . . about that . . .

For many of you, creating an AI probably seems daunting. However, there are a number of things you already "know" an AI needs to do to successfully land the rocket. For example:

So based on these questions, we already have some idea of how our AI needs to behave. At a minimum, our AI needs to be able to:

Let's go ahead and tackle each of these problems in turn.

PROBLEM 1: Slowing the Rocket's Vertical Descent

The first thing we should do is make sure that the rocket isn't descending too quickly. After all, we want to make sure our rocket (and its virtual passengers) lands intact!

Declare two variables at the top of run_autopilot() that represent:

  1. The maximum vertical velocity allowed (i.e., the maximum rate at which the rocket is allowed to descend)
  2. The amount of thrust that the rocket can apply in the vertical direction (i.e., the max acceleration per animation frame)

For now, give these variables any value you like, so long as the first is larger than the second. Then, write code that compares the rocket's current vertical velocity (which is passed to run_autopilot() as a parameter) to the maximum allowed velocity. If the rocket is travelling faster than the "speed limit", then apply thrust in the "up" direction to slow it down (remember that (0,0) in pythonGraph is the top left corner, and that POSITIVE Y is DOWN)

Try to add the code in run_autopilot() that slows the rocket down to a manageable speed. Here is a logic design in case you need it:

def run_autopilot(. . .):
    MAX_Y_VELOCITY  = 
    THRUST_AMOUNT_Y = 
    
    THRUST_UP = 0
    THRUST_RIGHT = 0
    THRUST_LEFT = 0
    
    1.  if the rocket's y velocity is greater than or equal to the MAX_Y_VELOCITY:
        1a.  Set THRUST_UP to thrust upwards

When you have finished writing your code, update your return values, and run your program. You should see your rocket's bottom thruster fire whenever its velocity surpasses the speed limit. Try experimenting with different speed limits and thruster amounts until the rocket behaves the way you would like.

Congratulations! You have created the first part of your AI. Naturally, there is more work to be done, as your rocket is still flinging itself uncontrollably to the right. That, however, is a problem for another day (or paragraph).

PROBLEM 2: Moving Towards the Boat

The second thing we need to do is make sure that the rocket moves towards the boat. This part is easy! When run_autopilot() is called by the main program, it is given the (x, y) coordinates of the rocket and the landing boat, as well as the width of each. It should be easy, therefore, to determine if the rocket is to the left or to the right of the boat, and to fire the appropriate thruster.

Don't believe us? Here are some quick examples:

Similar to the previous subsection, we need a variable that represents the amount of thrust that the rocket can apply in the horizontal direction. Create this variable at the top of run_autopilot(). Then, write the code that allows your AI to determine where the boat is (e.g., RIGHT or LEFT), and thrust in the appropriate direction. The following logic design should help you out:

def run_autopilot(. . .):
    MAX_Y_VELOCITY  = [SOME VALUE]
    THRUST_AMOUNT_Y = [SOME VALUE; should be smaller than above]
    
    THRUST_AMOUNT_X = [SOME VALUE]     # <-------------  THIS IS NEW
    
    THRUST_UP = 0
    THRUST_RIGHT = 0
    THRUST_LEFT = 0
    
    1.  if the rocket y velocity is greater than or equal to the MAX_Y_VELOCITY:
        1a.  Set THRUST_UP to thrust upwards
        
    2.  if the rocket is to the LEFT of the boat:           # <-------------  THIS IS NEW
        2a.  Set THRUST_RIGHT to thrust towards the boat    # <-------------  THIS IS NEW
    
    3.  if the rocket is to the RIGHT of the boat           # <-------------  THIS IS NEW
        3a.  Set THRUST_LEFT to thrust towards the boat     # <-------------  THIS IS NEW

When you have finished writing your code, run your program. You should see your rocket zoom towards the boat . . . and then shoot way past it

WHAT HAPPENED?!? Basically, your rocket presses the gas as soon as it enters the Landing phase. Consequently, by the time the rocket makes it to the boat, it is travelling so fast that it can't break fast enough to land.

In order to fix this, we need to have a way to restrict how fast the rocket can move in the horizontal direction. This brings us to the last part:

PROBLEM 3: Control the Rocket's Horizontal Speed

As shown above, we need a way to control the rocket's maximum x-velocity so that we don't wildly overshoot the rocket. Fortunately, we have already solved a similar problem. In PROBLEM 1, we created a variable that represented the maximum speed the rocket could travel in the y direction. Simply create another variable that represents the max velocity in the x-direction. Make sure that this value is larger than the x-thruster amount you defined in the previous section.

Once you have your variable, add code to run_autopilot() so that the thrusters only fire if the rocket is not at its maximum x-velocity. This logic is described in the following logic design.

def run_autopilot(. . .):
    MAX_Y_VELOCITY  = [SOME VALUE]
    THRUST_AMOUNT_Y = [SOME VALUE; should be smaller than above]
    
    MAX_X_VELOCITY = [SOME VALUE]                           # <-------------  THIS IS NEW
    THRUST_AMOUNT_X = [SOME VALUE]                          # <-------------  Update to be smaller than max_x_velocity
    
    # This was provided to you
    THRUST_UP = 0
    THRUST_RIGHT = 0
    THRUST_LEFT = 0
    
    1.  if the rockets y velocity is greater than or equal to the MAX_Y_VELOCITY:
        1a.  Set THRUST_UP to thrust upwards
        
    2.  if the rocket is to the LEFT of the boat:           
        2a.  if the rocket is not travelling to the right at its MAX_X_VELOCITY      # <-------------  THIS IS NEW
            - Set THRUST_RIGHT to thrust towards the boat    
    
    3.  if the rocket is to the RIGHT of the boat                                   # <-------------  THIS IS NEW
        3a.  if the rocket is not travelling to the left at its MAX_X_VELOCITY
            - Set THRUST_LEFT to thrust towards the boat

Testing

Once you have finished each of these steps, validate you have updated your return values, and run your program. You should see a rocket that generally tries to get closer to the landing boat and land. Please note that your AI may still end up crashing in the water. If this happens, try adjusting the maximum velocities and thruster amounts for x and y. With some tuning, you should find a set of values that yields reasonable performance.

At this point, you have a functional AI! That being said, it's clearly not perfect. The AI we provided you will land "most of the time", but also tends to be very inefficient (see how it is wobbles from side to side as it lands?)

If you have time, you may want to consider making additional improvements to your AI in order to improve its performance. Some of the ideas you could look into are:

Once you are happy with your AI's behavior, move on to the next page.

Proceed to the next section.