RoboCatz.com
About FLL | Navigation | Playbook | Strategy | Models | Techniques | RobotC | Programming | Robot News |

Playbook: Function Overloading -- The Exercise

Definition: The ability to define multiple functions with the same name but with different implementations.

driveForward();   // Just start driving forward
driveForward(12); // Just drive for 12 inches
driveForward(12,25); // Drive for 12 inches at 25% power
The types of function overloading we use are classified as a form of static polymorphism in which a function call is resolved using the 'best match technique', i.e., the function is resolved depending upon the argument list.

Function overloading is usually associated with statically-typed programming languages which enforce type checking in function calls. When overloading a function, you are really just making a number of different functions that happen to have the same name. When the program is "compiled", the compiler determines which of the functions are used in each instance.

Requirements

This exercise requires you to be in front of a computer with RobotC and a Mindstorms robot. You will write a program according to the instructions below. Try not to just jump to the end of the lesson and copy the whole program. You won't learn much by doing that. Follow the individual steps shown below. Follow them in order--so that you'll know what to do when you have to write your own programs some day.

Start RobotC and access a New program

Start RobotC then click on the New File button from the button bar. The new program should appear as:

task main()
{


}
Next, insert a function to draw a circle.
The function that you will insert will be: drawCircle(100, 50, 20);
After you insert it into your program, it should look like the code shown below.

task main()
{

  drawCircle(100, 50, 20);

}
Press the F5 key to run your program. Before the program runs, the computer will ask you to save your program and it will suggest a filename. You may change the name of the file as well as its location if you want. Press the F5 key and then press the Start button once it is highlighted.

Did you see the circle?


Probably not. The robot drew the circle and ended the program probably faster than you could see it. Let's make the robot wait a little bit.

task main()
{
  drawCircle(100, 50, 20);
  wait(2);
}
Run the program now. You should see the circle. Ok.

There it is. 100 on the x axis, and 50 on the y axis. From this, you can see that the origin point is the lower left corner of the display.

Now let's draw the circle at random positions on the display. To do this, we will use the function called random() Replace the values you currently have in the drawCircle() function with the random() function as shown below.

task main()
{
  drawCircle(random(100), random(100), random(20));
  wait(2);
}
Run it several times.

What do you see?

Do you see circles?

The reason is NOT intuitive and is probably just a bug in the RobotC compiler. There is a simple work around: just make sure you pass integers to the drawCircle function.

An integer is a whole number (not a fraction or a number with a decimal). You can declare variables to contain only certain types of numbers (for example: integers). To declare a variable as an integer, we use the int keyword prior to the variable name in its declaration statement (see example below).

task main()
{
  int x = random(100);
  int y = random(100);
  int r = random(20);
  drawCircle(x, y, r);
  wait(2);
}
Fix your program so that it looks like the one above and run it. Feel free to copy-and-paste the code directly into your program. If you use the copy and paste method, make sure you are overwriting the old statements in your program that you no longer need.

Reading the program above, we declare an integer x and assign (=) it a random number between 0 and 100. We declare a y integer to also contain a random number. Then we pass the two integers to the drawCircle() function.


Now Create Your Own Function

This is an exercise in function overloading--not just how to draw circles. The code which is currently being used to draw a circle will be moved into a function.

Sometimes you may want to use a function in multiple places within your program. ALL C LANGUAGES ALLOW YOU TO CREATE YOUR OWN FUNCTIONS!!! This is very important. C is powerful because you can customize it to meet your needs. And there are almost no limitations to the degree to which you can customize it.

Let's try something new. You'll create your own function called randomCircle(). Type the following before the main task as shown below:

void randomCircle() 
{

}

task main()
{
  int x = random(100);
  int y = random(100);
  int r = random(20);
  drawCircle(x, y, r);
  wait(2);
}
Now block and move the statements which drew the circle into the newly created function as shown below:

void randomCircle() 
{
  int x = random(100);
  int y = random(100);
  int r = random(20);
  drawCircle(x, y, r);
}

task main()
{

  wait(2);
}
Now we just need our program to use the new function we created. So we will add a randomCircle(); within the task main() as shown below:

void randomCircle() 
{
  int x = random(100);
  int y = random(100);
  int r = random(20);
  drawCircle(x, y, r);
}

task main()
{
  randomCircle();
  wait(2);  
}
We can "call" our function as many times as we want as in:

void randomCircle() 
{
  int x = random(100);
  int y = random(100);
  int r = random(20);
  drawCircle(x, y, r);
}

task main()
{
  randomCircle();
  randomCircle();
  randomCircle();
  randomCircle();
  randomCircle();
  wait(2);  
}

Animation

The robot will do what you tell it to do. So, let's tell it to draw circles for a long while as in:

void randomCircle() 
{
  int x = random(100);
  int y = random(100);
  int r = random(20);
  drawCircle(x, y, r);
}

task main()
{
   while(true)
  {
    randomCircle();
    randomCircle();
    randomCircle();
    randomCircle();
    randomCircle();
    wait(2);  
  }
}
Adding the while(true) loop allow the robot to continue executing the functions forever.

Faster Animations

You can speed up the drawing by reducing the wait time. Try changing the wait parameter to 0.2 which will make it 10 times faster.

Make the change to 0.2 and run the program.

How does it look now?

Overloading Functions

I can have multiple forms of the same function where each form may do something different depending on the number and types of parameters passed to it.

For example:

All 3 forms of the randomCircle function will draw circles. Each form specifies different combination of location and size.

Try adding the functions below to your program:

void randomCircle() { // Not specifying any parameters here.  All will be created with random numbers.
  int x = random(100);
  int y = random(100);
  int r = random(20);
  drawCircle(x, y, r);
}
void randomCircle(int r) { // Here, I am specifying r but not x or y.
  int x = random(100);
  int y = random(100);
  drawCircle(x, y, r);
}
void randomCircle(int x, int y) { // Here, I am specifying x and y but not r.
  int r = random(100);
  drawCircle(x, y, r);
}
task main()
{
  while(true)
  {
    //randomCircle(50, 50);
    randomCircle(100);
    wait(0.2);  
  }
}
It's the same function name: randomCircle(). But there are three different ways it can be referenced -- each with a different combination of parameters. This makes your program more flexible in that it can handle different combinations of functions and parameters.

Try It

Try using all three functions in the main task (see example below).

Can you tell which circle is being drawn by each function?

Try it.

task main()
{
  randomCircle( 50,  50, 30);
  randomCircle(150, 120);
  randomCircle(100);
  wait(10);  
}

Bonus Exercise

Just as you can draw circles, you can also draw squares. Squares are rectangles that have the same lengths for their width and height. The drawRect() function takes four parameters: x1, y1, and x2, y2.

A square with size (s) is shown as:

drawRect(x, y, x+s, y+s);

A randomSquare function would be defined as follows:

void randomSquare(int s) {
  int x = random(100);
  int y = random(100);
  drawRect(x, y, x+s, y+s);
}
Your task main() could use the function as:

task main()
{
  int squareSize=50;
  while(true)
  {
    randomSquare(squareSize);
    wait(0.2);  
  }
}

Overloaded Functions to Move the Robot

Consider the following example of overloaded functions:

driveForward();Just make the robot start driving forward (for infinity).
driveForward(12);Make the robot drive forward for 12 inches.
driveForward(12, 50);Make the robot drive forward for 12 inches at 50% power.

These are three different but very useful ways of making the robot do a similar task: driving forward.
Each of these functions use parameters (or lack of) to specify how the robot should drive forward.



Start a new program and save it as a new filename.

task main()
{


}
Add a basic drive forward function.

void driveForward() {
  setMotorSync(B, C, 0, 20);
}

task main()
{


}
Let's add a function for driving a specific distance. In order to implement this, we will need to include a function that lets the robot know how far it has traveled.

#define PI 3.14159
typedef struct genericRobotStruct { // Create a generic structure to store things such as powerLevel, wheelDiameter, gearRatio, etc.
  int powerLevel;
  int wheelDiameterMM;
  int gearRatio;
  int distanceBetweenWheelsMM;
  bool criteriaNotMetYet;
} robotObj; robotObj robot;

void untilDistance(int moveIN) {
  resetMotorEncoder(B);
  resetMotorEncoder(C);
  float targetDegree;
  targetDegree=(moveIN * 25.4)/(robot.WheelDiameterMM*PI)*360;
  repeatUntil(abs(getMotorEncoder(B)) > targetDegree) { sleep(5);	}
}

void driveForward() {
  setMotorSync(B, C, 0, robot.powerLevel);
}
// Overloaded function
void driveForward(int distance) {
  driveForward();
  untilDistance(distance);
  stopAllMotors();
}
// Another Overloaded function
void driveForward(int distance, int pwr) {
  setMotorSync(B, C, 0, pwr);
  untilDistance(distance);
  stopAllMotors();
}


task main()
{
  robot.wheelDiameterMM = 43.2;
  robot.distanceBetweenWheelsMM = 130;
  robot.powerLevel=40;

  driveForward(12);

}
If your robot doesn't move exactly the distance you specified, then you may need to increase or decrease the wheel diameter property of the robot object shown in the main task.

Now you should be able to use functions such as:

task main()
{
  robot.wheelDiameterMM = 43.2;
  robot.distanceBetweenWheelsMM = 130;
  robot.powerLevel=40;

  driveForward(12);
  driveForward(12,100);
  driveForward();
  untilDistance(48);

}