Writing Your First Behavior

This document will walk you through the creation of your first Behavior.  Behaviors are high level programs which direct the robot to complete some task, comparable to an application on a PC.  Following this guide will give you a behavior which will light up LEDs corresponding to which button is pressed.

Prerequisites

  1. You should read through the Doxygen documentation on the BehaviorBase class.

  2. If you're rusty or new to C++, there is a C++ review available, which goes into more detail regarding the boilerplate given below.

The Generic Behavior

  1. First, create a file named SampleBehavior.h (or whatever you want to call it) in your project directory.

  2. Set up the usual C++ boilerplate, inheriting from the BehaviorBase class.  This class defines the interface which all Behaviors must follow, and provides some simple housekeeping code.

    SampleBehavior.h
    //-*-c++-*-
    #ifndef INCLUDED_SampleBehavior_h_
    #define INCLUDED_SampleBehavior_h_

    #include "Behaviors/BehaviorBase.h"

    class SampleBehavior : public BehaviorBase {
    public:
    SampleBehavior() : BehaviorBase("SampleBehavior") {}

    virtual void DoStart() {BehaviorBase::DoStart();}
    virtual void DoStop() {BehaviorBase::DoStop();}
    };

    #endif

    If this looks scary to you, look over the C++ review.

    There is a template file in <project>/templates/behavior.h which will save you some time of typing the boilerplate each time.

    NOTE: Comments such as // [...] indicate placeholders for code which is not shown in the code fragment.

    These functions define the BehaviorBase interface.  You will see -*-c++-*- comments at the top of many of our header files - this is a flag to Emacs that it should use C++ mode instead of C mode for syntax hilighting and formatting.  You can ignore it.

  3. At this point, you have a valid behavior. All that remains is to add a call to it from the framework so you can activate it.  The recommended way to do this is to add an entry into the menu system you get during E-Stop.  This menu system consists of various Controls (see ControlBase), one of which is BehaviorSwitchControl.  This control will activate a behavior when the corresponding menu item is selected.

    There is one, and only one, "special" behavior which you will need to know - StartupBehavior.  This behavior is activated automatically by the Main process once the system is initialized.  This behavior sets up the menu system and activates any behaviors which you wish to have start up automatically.  You could add a call to your behavior from within StartupBehavior::DoStart(), or even replace StartupBehavior with your own behavior, but for better practice, let's add it into the menu system so you can turn it off and on at will.

    So, there's two things you need to do: add an #include for your header file, and add the menu entry itself.

    Since the construction of the menu items requires including header files for every behavior and control which is to be included, StartupBehavior can take a long time to compile.  To fix this, we have broken the menu construction into several compilation units which are then linked together.  The benefit of this is that if a header file for one of these units changes, only that part of StartupBehavior needs to be recompiled, which will save you a significant amount of time.

    So, in your project folder, you should see a series of StartupBehavior files.  Each of the StartupBehavior_Setup* files sets up a single item in the root Controller menu, and is called by StartupBehavior::SetupMenus().  We want to edit the Mode Switch menu.

    Put the header file #include near the top (of StartupBehavior_SetupModeSwitch.cc)  You'll see where a bunch of other behaviors are included.  Near the middle of the file, look for the FollowHeadBehavior entry.  Just copy that and add another entry.  It should look like:

    StartupBehavior_SetupModeSwitch.cc
    // [...]
    #include "SampleBehavior.h"

    ControlBase*
    StartupBehavior::SetupModeSwitch(Controller& controller) {
    // [...]
    addItem(new BehaviorSwitchControl<SampleBehavior>("SampleBehavior",bg,false));
    addItem(new BehaviorSwitchControl<FollowHeadBehavior>("FollowHeadBehavior",bg,false));
    // [...]
    }

    The bg is a behavior group, which means that when the control is activated, it automatically deactivates the previously running behavior in that group.  The false argument controls whether (or not in this case) to retain the behavior's memory space between activations.  A large behavior could be slow to start and stop if it is not retained (but also would then waste memory when not in use).

  4. Now just go to the root Tekkotsu directory and type make update.  If you've set up the framework, everything should build and copy to the memory stick.  Then just put the memory stick into the Aibo and turn it on!  (Be sure to "unpause" by double-tapping the back button to turn off the emergency stop mode.)

Further exercises

  1. You can put a cout in the DoStart() and DoStop() functions to make "Hello world".  (Remember, telnet to port 59000 on the dog to see the output)
  2. Adding sound is really easy.  Take a look at SoundManager to make a dog-like version of "Hello World" (a.k.a. "Woof! Woof!")

  3. Shawn Turner of the University at Albany has written two tutorials, Introduction to Behaviors using Tekkotsu and Writing Finite State Automata in Tekkotsu which may be of interest.  (Local cached PDFs are available from the Media page)

  4. For future reference, there's a empty shell of a behavior for quickly making new behaviors at <project>/templates/behavior.h.  But it's better to write your own the first time so you know what it means, which is why it wasn't mentioned earlier. ;)

  5. Part 2: Adding Behavior Functionality will show you one way to control the LEDs.