Learning Python 3 with the Linkbot/Debugging

From LinkbotLabs
Jump to: navigation, search
 Next Generation Science Standards: MS-ETS1-3 Analyze data from tests to determine similarities and differences among several design solutions to identify the best characteristics of each that can be combined into a new solution to better meet the criteria for success.


What is debugging?

"As soon as we started programming, we found to our surprise that it wasn't as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life from then on was going to be spent in finding mistakes in my own programs." — Maurice Wilkes discovers debugging, 1949

By now if you have been messing around with the programs you have probably found that sometimes the program does something you didn't want it to do. This is fairly common. Debugging is the process of figuring out what the computer is doing and then getting it to do what you want it to do. This can be tricky. It surprisingly common to spend weeks tracking down and fixing a bug that was caused by someone putting an x where a y should have been.

This chapter will be more abstract than previous chapters.

What should the program do?

The first thing to do (this sounds obvious) is to figure out what the program should be doing if it is running correctly. Come up with some test cases and see what happens.

For instance, lets try to write a program that rolls a Linkbot-I with two wheels forward one rotation while making the LED green, and then rolls the Linkbot backward with the LED red. Here's a first try at this program:

# File: 01_debug.py
import linkbot
 
myLinkbot = linkbot.CLinkbot('ABCD') # Change 'ABCD' to your Linkbot's Serial ID
 
myLinkbot.moveNB(360, 0, -360)    # Roll Forward
myLinkbot.setLedColor(0, 255, 0)  # Set LED to green
myLinkbot.moveNB(-360, 0, 360)    # Roll Backward
myLinkbot.setLedColor(255, 0, 0)  # Set the LED color to red

At first glance, the above program may appear to be correct. When you actually try it though, you'll see that the robot never turns its LED green, and it never moves forward. It immediately changes its LED red and moves backward. What happened to the two lines that are supposed to make the robot roll forward and turn the LED green?

One easy and powerful method of debugging problems like this is to use the print() function to track the progress of the program while it's running. Lets try adding some print statements to our original program and see if we can track down the problem:

# File: 02_debug.py
import linkbot
 
myLinkbot = linkbot.CLinkbot('ABCD') # Change 'ABCD' to your Linkbot's Serial ID
 
print("Moving forward...")
myLinkbot.moveNB(360, 0, -360)    # Roll Forward
print("Done. Setting LED to green...")
myLinkbot.setLedColor(0, 255, 0)  # Set LED to green
print("Done. Moving backward...")
myLinkbot.moveNB(-360, 0, 360)    # Roll Backward
print("Done. Setting LED to red...")
myLinkbot.setLedColor(255, 0, 0)  # Set the LED color to red
print("Done.")

When you run this program, pay attention not only to what it's printing, but also how and when it's printing. When you run the program, the output you should get is:

Moving forward...
Done. Setting LED to green...
Done. Moving backward...
Done. Setting LED to red...
Done.

However, you'll notice that all of those statements print immediately; there is no delay between the commands that tell the robot to move forward and the commands that tell it to move backward. That should immediately give us an indication for what is wrong: the program should wait until the robot is finished moving forward before moving backward and turning red. You'll notice that we used non-blocking movement functions in our program so that we can move and change the LED color at the same time. However, we also know that Python doesn't stop and wait at non-blocking and "set" functions. From the previous chapter, we also have a function that makes Python wait until a non-blocking motion is completed called moveWait(). Lets try fixing our broken program:

# File: 03_debug.py
import linkbot
 
myLinkbot = linkbot.CLinkbot('ABCD') # Change 'ABCD' to your Linkbot's Serial ID
 
myLinkbot.moveNB(360, 0, -360)    # Roll Forward
myLinkbot.setLedColor(0, 255, 0)  # Set LED to green
myLinkbot.moveWait()              # Wait until the robot is finished rolling forward
myLinkbot.moveNB(-360, 0, 360)    # Roll Backward
myLinkbot.setLedColor(255, 0, 0)  # Set the LED color to red

A moveWait() statement has been added in-between the two steps. This forces Python to wait until the robot is done moving forward before telling it to move backward and set the LED color to red.

Without the moveWait() statement, Python will go through all of those statements so fast that the robot rolling forward and green LED won't be noticeable to human eyes and ears. Only the last commands, rolling backward and the red LED, "stay" on the robot and are observable, making it seem like Python was skipping the moving forward and green LED altogether.

General Tips

  1. This may sound obvious, but the first thing to ensure is that you know what the program is supposed to do.
  2. Check to make sure the program flow is correct by using print() statements.
  3. Check to make sure variable values are correct using print() statements.
  4. For complex programs that might use loops and variables, try "stepping" through the program, line by line, keeping track of variable values and program outputs using pen and paper.
  5. If you have a long program that does many calculations on a variable and the value of the variable is wrong at the end of the program, try using the "binary-search" method to find the bug: Use a print() statement to check the value of the variable in the middle of the program. If the value is correct, you know the bug is somewhere in the second half of your program. Put another print() statement in the middle of the second half of the program and check its value. Repeat until you've found the incorrect line of code that is incorrectly setting the variable's value. This technique is highly useful for finding where a bug might be occurring, and it is useful for many types of bugs.
Learning Python 3 with the Linkbot
 ← Decisions Debugging Defining Functions →