View unanswered posts | View active topics It is currently Thu Oct 23, 2014 3:14 pm






Reply to topic  [ 15 posts ] 
Multitasking [sticky] - When and When Not to Multitask 
Author Message
Site Admin
Site Admin

Joined: Mon Jun 08, 2009 4:50 pm
Posts: 70
Post Multitasking [sticky] - When and When Not to Multitask
Multitasking is when the robot performs multiple complex behaviors at the same time (simultaneously). If a robot performs behaviors step-by-step (sequentially) then it is not multitasking and should not be programmed with multiple tasks. Let’s look at few examples and determine whether or not multitasking should be used.

A robot drives forward until the sonar sensor sees and object at 30 cm or less away, turns right and stops.

A flowchart of this program would look like this:
Code:
Program starts,
Motors start going forward,
Keep going until the sonar sees something <= 30 cm,
Turn right (right motor negative, left motor positive),
Stop (both motors at 0),
End Program.


As you can see, this program is sequential because each step comes after the one above it. We DO NOT use multitasking in this example. Let’s look at another:

A robot follows a line until it is 20 cm or less away from a basket and then drops a ball into the basket.

A flowchart of this program would look like this:
Code:
Program starts,
Sonar starts checking for objects <= 20 cm away,
Light sensor reads dark:
   Motors turn slightly one direction,
Light sensor reads light:
   Motors turn slightly in the other direction,
Sonar sees the basket <= 20 cm away,
Motors stop,
Arm motor starts and drops ball into basket,
End Program.


This program also runs from top-to bottom, but this time we have a sonar sensor and a light sensor that are checking their values and performing behaviors at the same time.
Should we use multiple tasks here? No because we can combine the multiple behaviors into a single task like this:

Code:
task main()
{
   // do the things in this loop while the sonar sensor is > 30 cm
   while(SensorValue(sonar) > 30)
   {
      // follow line:
      if(SensorValue(lineFollower) < threshold)
      {
         // turn sligtly one direction
         motor[rightMotor] = 50;
         motor[leftMotor] = 0;
      }
      else
      {
         // turn slightly in the other direction
         motor[rightMotor] = 0;
         motor[leftMotor] = 50;
      }
   }
   
   // stop motors and dump ball into basket:
   motor[rightMotor] = 0;
   motor[leftMotor] = 0;
   motor[armMotor] = 25
   wait1Msec(1000);
   motor[armMotor] = 0;
}
 


When multiple behaviors can be combined into a single task, we should always choose to do so instead of multitasking!

When should one use multitasking then? Imagine a program that drives a robot around a room vacuuming up objects while avoiding people. The robot comes with an emergency stop button just incase the systems for avoiding people fail or the robot uprising begins and we need to deactivate our robot quickly (in the real world, kill switches are important for human safety). How would a flowchart for this program look like? It is difficult to make a linear step-by-step chart for this program because it is doing multiple things at the same time. Also, the emergency stop button needs constantly be checking while other behaviors are running because the robot must stop immediately when the button is pressed, no matter what else it may be doing at the time. We need multiple flow charts side-by-side:


Driving flowchart:
Code:
Start program,
Turn on vacuum,
Start driving around,
If sonar sees a person:
   stop motors,
   turn off vacuum,
Sonar no longer sees person:
   turn on vacuum,
   contine driving around,
Loop back to start of program.   


E-stop flowchart:
Code:
Begin loop:
If E-stop button pressed:
End Program.
If E-stop button not pressed:
Go back to top of loop,


The actual program would look something like this:

Code:
task e_stop()
{
   while(true)
   {
      if(SensorValue(e_stopBtn) == 1)
      {
         StopAllTasks(); // this ends the program
      }
      wait1Msec(10);  // this prevents the current task from hogging the CPU
   }
}


task main()
{
   StartTask(e_stop);
   while(true)
   {
      if(SensorValue(sonar) <= 10)
      {
         motor[rightMotor] = 0;
         motor[leftMotor] = 0;
         motor[vacuumMotor] = 0;
      }
      else
      {
         // code for driving around room here
      }
      wait1Msec(10);  // this prevents the current task from hogging the CPU
   }
}


Notice that even though behavior for picking up objects and the behavior for avoiding people are running at the same time, they can be combined into a single task. However, the emergency stop button requires a task on its own that runs in the background while the other behaviors are also running. Also please note the two “wait1Msec” commands that prevent each task from hogging the CPU. If a task doesn’t have any waiting in it, it may hog the CPU meaning that it will not let any other tasks run.

It’s important to remember that task main is the main task of the program and when it finishes execution, all other tasks will be force-quit and the program will end. In our example, task main was always in a while(true) loop and didn’t end until task e_stop stopped all tasks.

This very basic example shows a good use for when to use multitasking, however many very important and dangerous concepts have not been addressed.
I encourage those who wish to know more to research Multitasking (multi threading) in C.


Remember:
99% of all ROBOTC programs can be written without multiple tasks if you combine related behaviors!

and
99.9% of all errors in programs that use multitasking are because of improper use of multitasking!!

_________________
Bence Feher

Undergraduate Intern - NREC, Robotics Academy
ROBOTC - Testing/Documentation/Developer

Computer Science, Japanese, East Asian Studies
University of Pittsburgh, Konan University 甲南大学


Wed Jun 22, 2011 1:16 pm
Profile
Site Admin
Site Admin

Joined: Tue May 15, 2007 9:02 am
Posts: 405
Post Re: Multitasking [sticky] - When and When Not to Multitask
Nice post!

_________________
Jesse Flot
CMU Robotics Academy
ROBOTC Support


Thu Jun 23, 2011 2:08 pm
Profile
Rookie

Joined: Sat Nov 22, 2008 8:06 pm
Posts: 48
Post Re: Multitasking [sticky] - When and When Not to Multitask
100% of all programs can be written without multiple tasks on a single core microcontroller, unless you consider any interrupt a different task, in which case 0% of ROBOT C programs can be written without multiple tasks, because the Robot C operating system is interrupt driven.

Any program can be written without using multiple task, it just a matter of whether it's worth the time and skill to do it.


Sat Aug 27, 2011 12:08 am
Profile
Moderator
Moderator
User avatar

Joined: Tue Sep 14, 2010 9:19 pm
Posts: 496
Post Re: Multitasking [sticky] - When and When Not to Multitask
Quote:
Any program can be written without using multiple task, it just a matter of whether it's worth the time and skill to do it.

In some programs, multitasking is definitely the more elegant solution. While writing that program without multitasking may be possible, and it may take skill, it's not necessarily the best way to go about it. Multitasking is a tool, and should be used in the proper circumstances. The problems arise when people use this tool in the improper circumstances.

_________________
sudo rm -rf /


Sat Aug 27, 2011 6:42 am
Profile
Rookie

Joined: Sun Sep 18, 2011 3:54 am
Posts: 2
Post Re: Multitasking [sticky] - When and When Not to Multitask
Multi-tasking is a tricky issue.
Usually it requires knowing about things like semaphores, locks, etc.
RobotC Cortex seems to have a very very rudimentary multi-tasking
basically StartTask StopTask and some priority/time slice functions.
nothing to support/prevent contention on variables, sensors, motors, etc
and no way to WaitForTaskToComplete()

or is this documented elsewhere than http://www.robotc.net/support/vex/WebHelpCortex/ ?


Sun Sep 18, 2011 4:15 am
Profile
Rookie

Joined: Mon Jan 10, 2011 11:39 pm
Posts: 16
Post Re: Multitasking [sticky] - When and When Not to Multitask
A Reply for the poster above:
Its actually not documented but they have some sort of support for semaphores, its really basic and requires you to do most of the checking, its basically just a struct which the firmwares puts information to, like which task owns it and if it is locked or not. Its new with 3.0, you will see it on the cortex platform under Semaphore in the sidebar. As for waiting for a task to complete, you can bypass that by using global variables, for instance a boolean that holds the status and you just create a while loop to keep checking. Example:

boolean Completed = false;
StartTask(exampleTask);
while (Completed == false) {};

BE AWARE: this will cause the task your running this code from to freeze until "exampleTask" has finished executing which can lead to problems if it gets stuck in some sort of infinite loop.

_________________
Regards
Stefan Andres Charsley
charsleysa@gmail.com


Wed Sep 28, 2011 12:48 am
Profile
Moderator
Moderator
User avatar

Joined: Wed Mar 05, 2008 8:14 am
Posts: 3227
Location: Rotterdam, The Netherlands
Post Re: Multitasking [sticky] - When and When Not to Multitask
Consider using these new functions in 3.x:

Attachment:
Screenshot-2011-09-29_20.15.45.png
Screenshot-2011-09-29_20.15.45.png [ 6.31 KiB | Viewed 14350 times ]


- Xander

_________________
| Professional Conduit of Reasonableness
| (Title bestowed upon on the 8th day of November, 2013)
| My Blog: I'd Rather Be Building Robots
| ROBOTC 3rd Party Driver Suite: [Project Page]


Thu Sep 29, 2011 2:17 pm
Profile WWW
Rookie

Joined: Sat Dec 17, 2011 9:27 pm
Posts: 1
Post Re: Multitasking [sticky] - When and When Not to Multitask
I'm new to robotC (or programming in general) and am having a hard time getting a handle on the idea of linear steps. I'm much more comfortable with PLC ladder logic and am trying to make robotC work in a similar fashion.

I've been trying to write a program that would, basically, turn on a motor and reverse it's direction at time intervals. While this is going on I want to use a limit switch to stop and start another motor.

I think I'm making this far more complicated than it needs to be. I've been playing around with task control etc but I don't even know what I don't know.

Can anybody suggest some ways I might be able to approach the problem stated above?


Sat Dec 17, 2011 9:36 pm
Profile
Moderator
Moderator
User avatar

Joined: Tue Sep 14, 2010 9:19 pm
Posts: 496
Post Re: Multitasking [sticky] - When and When Not to Multitask
Maybe this question should be in a separate thread. You could use boolean flags to make this work without multitasking, but multitasking might make it easier. How do you want the switch to control the second motor? Run it while the switch is pressed and stop when released? Or run when the switch is pressed and released, and stop when it's pressed and released again?

_________________
sudo rm -rf /


Sun Dec 18, 2011 12:32 am
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: Multitasking [sticky] - When and When Not to Multitask
From my point of view, there are two ways of doing multiple things at the same time. You can either use the "task" feature in RobotC. The task feature in RobotC is implementing preemptive multi-tasking which has a lot of gotcha's especially if you are accessing common resources in multiple tasks. Or you can do cooperative multi-tasking. The main idea of cooperative multi-tasking is to write a function for each task and make sure each of these functions do not block (i.e. you should never call any wait1Msec, wait10Msec etc or have any loops in the function). Whenever you need to wait for something to happen, remember where you are and return instead so another task can run. When your task is run again, retrieve the state where you were and continue. To explain it better, I always use the example of baking a pizza and doing laundry at the same time. First list out the steps for baking a pizza.
Code:
Set the oven to pre-heat temperature of 400 degree F;
Wait for the oven to reach the pre-heat temperature;
Put the frozen pizza into the oven;
Set a timer for 20 min;
Wait for the timer to ding;
Take the pizza out and serve it;

Next, list out the steps for doing laundry.
Code:
Put the clothes into the laundry machine;
Put detergent/softener into the dispenser;
Start the washing machine;
Wait for the washing machine  to finish;
Transfer the clothes from the washing machine to the dryer;
Start the dryer;
Wait for the dryer to finish;
Take out the clothes and fold them;
Put them away;

If you are smart, you are not going to stare at the oven while it is pre-heating or stare at the washing machine while it is washing your clothes. Instead, you leave and do something else and come back to check on it later. That's what multi-tasking is about. Imagine the above steps to bake a pizza or doing laundry are written as separate functions. If you call one function then the other, you are serializing the two tasks. One cannot start before the other is completed. However, if you structure your functions like the following, it will do both tasks simultaneously.
Code:
int pizzaNextStep = 1;
int laundryNextStep = 1;
void PizzaTask()
{
    switch (pizzaNextStep)
    {
        case 1:
            Set the oven to pre-heat temperature of 400 degree F;
            pizzaNextStep++;
            break;

        case 2:
            if (pre-heat temperature has been reached)
            {
                pizzaNextStep++;
            }
            break;

        case 3:
            Put the frozen pizza into the oven;
            Set a timer for 20 min;
            pizzaNextStep++;
            break;

        case 4:
            if (timer has ding'd)
            {
                pizzaNextStep++;
            }
            break;

        case 5:
            Take the pizza out and serve it;
            pizzaNextStep++;
            break;

        default:
            Done;
            break;
    }
}

void LaundryTask()
{
    switch (laundryNextStep)
    {
        case 1:
            Put the clothes into the laundry machine;
            Put detergent/softener into the dispenser;
            Start the washing machine;
            laundryNextStep++;
            break;

        case 2:
            if (washing machine has stopped)
            {
                laundryNextStep++;
            }
            break;

        case 3:
            Transfer the clothes from the washing machine to the dryer;
            Start the dryer;
            laundryNextStep++;
            break;

        case 4:
            if (dryer has stopped)
            {
                laundryNextStep++;
            }
            break;

        case 5:
            Take out the clothes and fold them;
            Put them away;
            laundryNextStep++;
            break;

        default:
            Done;
            break;
    }
}

task main()
{
    while (true)
    {
        PizzaTask();
        LaundryTask();
    }
}

Since these two tasks are actually running on the same thread, there is no resource contention problem or synchronization issue. In essence, your task main loop is the task scheduler. It calls the next task when the previous task is willingly giving up processing. And it is doing this over and over again until all the tasks are completed.


Sun Dec 18, 2011 3:33 am
Profile
Moderator
Moderator
User avatar

Joined: Tue Sep 14, 2010 9:19 pm
Posts: 496
Post Re: Multitasking [sticky] - When and When Not to Multitask
I am not familiar with how the multitasking is done internally in ROBOTC. Would the "cooperative multitasking" that you mentioned above actually execute faster than the method that ROBOTC offers, or would the function overhead make it execute slower? Perhaps I'll run some tests when I get my hand on a cortex again.

_________________
sudo rm -rf /


Sun Dec 18, 2011 10:27 am
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: Multitasking [sticky] - When and When Not to Multitask
It's not about faster or slower. It's about more controlled. In preemptive multi-tasking, the scheduler is on time slices. If a time slice is expiring, the task is suspended regardless of what it is in the middle of processing. I am sorry. I am not familiar with the Cortex so I will show an example of the NXT. For example, in joystickDriver.c.
Code:
if(!bOverrideJoystickDisabling)
{
  bTempUserMode = joystickCopy.UserMode;
  bTempStopPgm = joystickCopy.StopPgm;

  memset(joystickCopy, 0, sizeof(joystickCopy));

//
// What if the scheduler decided your time slice is up right here?
//

  joystickCopy.UserMode = bTempUserMode;
  joystickCopy.StopPgm = bTempStopPgm;
  joystickCopy.joy1_TopHat = -1;
  joystickCopy.joy2_TopHat = -1;
}
bDisconnected = true;

If the above code got preempted at the specified spot, autonomous will get started erronously when communication is lost for a split second because StopPgm would have been zero'd briefly. That's just one of the gotcha's you will hit when programming with preemptive multi-tasking (accessing a common resource in multiple tasks). In this case, the common resource is the joystickCopy structure.
Regarding performance, cooperative multi-tasking puts the scheduling in your own hand. If you task mis-behaved (e.g. have a wait or a loop in your task), the other tasks are going to be starved (hence cooperative).


Sun Dec 18, 2011 10:56 am
Profile
Moderator
Moderator
User avatar

Joined: Tue Sep 14, 2010 9:19 pm
Posts: 496
Post Re: Multitasking [sticky] - When and When Not to Multitask
Couldn't you just use hogCPU() and releaseCPU() to make sure that your tasks aren't interrupted at critical moments?

_________________
sudo rm -rf /


Sun Dec 18, 2011 11:46 am
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: Multitasking [sticky] - When and When Not to Multitask
Yes, but then you are assuming you are aware of where in the code you need to protect by critical section. Sometimes this may not be obvious and hence hard to find bugs.


Sun Dec 18, 2011 2:09 pm
Profile
Rookie

Joined: Thu Nov 29, 2012 3:47 am
Posts: 1
Post Re: Multitasking [sticky] - When and When Not to Multitask
Thanks for the post...

_________________
http://www.wisc.edu/
http://www.mybraindumps.net/10g-OCA-guide.html
http://www.checkpoint.com/
http://www.youtube.com/user/accessdatagroup
http://en.wikipedia.org/wiki/Hitachi


Thu Nov 29, 2012 3:49 am
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 15 posts ] 

Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  



Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.