Previous Page TOC Index Next Page

BeeSoft User's Guide and Reference

2.6 Writing Your First Robot Program


In this section, you’ll learn how to write and run your first BeeSoft-based robot application program. To do this, you’ll:

1. create a test directory to work in;
2. copy over some BeeSoft supplied example files to use as "scaffolding" for your test application;
3. write an application routine, called a client function. You’ll use the data structures and functions in BeeSoft-supplied modules;
4. write the code to create a module for the robot function you want to invoke. You’ll need to determine scheduling for the function invocations, too;
5. write code to initialize the program; create all BeeSoft and user modules you need; and fire up the BeeSoft Scheduler;
6. compile and link your test code into an executable program;
7. run your program.

Let’s get started right now. Return to the demo home directory, set up a test directory to work in, go to it, and get yourself copies of some BeeSoft-supplied example files to modify for your test. Be sure to type the dots at the ends of the cp, or copy, commands! Type:

 cd ~
 mkdir  myTest
 cd  myTest
 cp ~bee/src/beeExamples/Makefile.simple Makefile .
 cp  ~bee/src/beeExamples/simple.c  

For now, don’t worry too much about such things as just what the BeeSoft Scheduler is or how it works. This, and other programming details, are explained fully in the section of this manual on Robot Programming.

For this very simple test application, you’ll use the BeeSoft-supplied API called baseClient, which presents you with a straightforward, transparent way of examining feedback from the robot’s sensors. This test application, called simple, looks only at the robot’s frontmost sonar sensor, and calculates a velocity based on the value of that sonar’s current reading, that is, based on how far it thinks it is from the nearest obstacle dead ahead.

The velocity chosen is designed to maintain a constant distance from the closest objectperceivable to the frontmost sonar sensor. The distance defaults to 100 centimeters, but you can change this value with a command line argument. simple will display this chosen velocity approximately once per second.

Please note: The code reproduced below is from the program simple.c, the one you just copied into your myTest directory. So, you don’t need to type in this code! After you understand how simple.c works, you’ll be using your own copy (in the directory myTest) to make modifications and build on the simple.c template to expand your knowledge of robot programming.

Writing the Module Function

/*============================================================*/
/*   simple.c
/*============================================================*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <math.h>
#include <baseClient.h>
#include <rai.h>
#include <bUtils.h>
/*============================================================*/
RaiModule* demoModule;
static int front;
static float distance;
static float maxSpeed;
static int limp;
/*============================================================*/
void
demoPoll (RaiModule * demoModule)
{
     float vel;
     static int count = 100;
     vel = ((float)sonars[front].value/10.0-distance)/2.0;
     If (vel > maxSpeed) {
          vel = maxSpeed;
     }
     If (vel < -maxSpeed) {
          vel = -maxSpeed;
     }
     if (count ++ > 10) {
          printf ("vel = %8.2f sonars[%d] = %8.2f\n",
          vel, front, (float)sonars[front].value/10.0);
          count = 0;
     }
     If ( limp ) {
          translateLimp ( );
          rotateLimp ( );
     }
     else {
          bSetVel (0.0, vel);
     }
     return;
}
/*============================================================*/ 

Creating the Module

createDemoModule below, informs the BeeSoft Scheduler that simple is to be scheduled, specifies termination and error behavior and sets initial values. The addPolling call tells the BeeSoft Scheduler that simple should be executed every time the specified polling interval — 100 milliseconds -- expires.

/*============================================================*/
void createDemoModule( )
{
     int ii;
     front = 0;
     /* Find the sonar sensor closest to the front. */
     for (ii=1; 11<bRobot.sonar_cols[0]; ii++) {
     If (fabs(bSonarAngle(0,ii)) < fabs(bSonarAngle(0,                  front))) {
               front = ii;
          }
     }
/* Ask that polling function be run every 100 msecs. */
demoModule= makeModule ("simple", NULL);
addPolling (demoModule, demoPoll, 100);
}
/*============================================================*/ 

Creating the Shutdown Function

commShutdown terminates baseServer and cleanly shuts down the application.

/*============================================================*/
void
commShutdown ( )
{
     printf ( "baseServer has exited. Exiting. \n" );
     RaiShutdown ( );
}
/*============================================================*/ 

Putting the Pieces Together

With all the pieces in place — the code to create the test module, the polling function and the shutdown function — we can set up the needed local parameters, initialize everything and start up the BeeSoft Scheduler to start scheduling

/*============================================================*/
int
main ( int argc, char** argv )
{
     /* Establish and clear the space for the structure
     /* for the module’s local parameters list. */
     struct bParamList * params = NULL;
     /* Put some default values into the local */
     /* parameters list. */
     /* Set the default distance to be maintained to the */
     /* nearest obstacle to the frontmost sonar at 100 mm*/
     params=bParametersAddEntry (params, "", "distance",
         "100" );
     /* Set the robot’s max. speed at 30 cm per sec. */
     params=bParametersAddEntry (params, "", "maxSpeed",
          "30" );
     /* Specify that controls aren’t initially ‘limp’. */
     params=bParametersAddEntry (params, "", "limp", "no" );
     /* Add params from BeeSoft’s std parameter file. */
     params=bParametersAddFile (params, "etc/beeSoft.ini" );
     /* Add in an environment variable, that is, the */
     /* TCX host name. */
     params=bParametersAddEnv (params, "", "TCXHOST" );
     /* Add in any cmd line arguments passed in by the */
     /* caller, overriding BeeSoft and program defaults. */
     params=bParametersAddArray (params, "", argc, argv );
     /* Put all this parameter info. Into the */
     /* global bRobot structure. */
     bParametersFillParams ( params );
     /* Extract selected values from the parameter */
     /* list as strings, so we can tell the user what
     /* the values are. */
     /* Get the distance, so we can tell the user. */

distance = atof(bParametersGetParam(params, "",

"distance")); /* Get the maximum speed, so we can tell the user. */ maxSpeed = atof(bParametersGetParam(params, "", "maxSpeed")); /* Get the limping status, so we can tell the user. */ limp =bStrToTruth(bParametersGetParam(params, "", "limp")); /* Tell the user what the values are. */ printf ( " \n**********************************\n\n" ); printf ( " -distance = %f\n", distance ); printf ( " -maxSpeed = %f\n", maxSpeed ); printf ( " -limp = %d\n", limp ); printf ( " \n**********************************\n\n" ); /* Initialize the BeeSoft Scheduler. */ RaiInit ( ); /* Initialize the baseServer client library. */ registerBaseClient ( ); /* Connect this process to TcxServer. If any of the */ /* connected TCX procs exits, call comm Shutdown. */ initClient ( "simple", commShutdown ); /* Connect baseServer client library to baseServer. */ findBaseServer ( ); /* Install some default signal handlers. */ catchInterrupts ( ); /* Set up scheduling info for TCX communications. */ initClientModules ( ); /* Set up this sample application program, simple.) createDemoModule ( ); /* Start the BeeSoft Scheduler. This effectively */ /* begins the operation of the program simple. */ RaiStart ( ); return (0); } /*============================================================*/

Compiling and Linking Your Robot Test Program

Remember that example makefile you copied into your own myTest directory? That’s what you’ll use here. Type:

 make simple

The compiler generates an executable called simple, that implements this simple test application.

Running Your Robot Test Program

Before calling your new client program ensure that the tcxServer and baseServer programs are running. Type

 tcxServer
 baseServer 

If you’d like to change any of the default values, here’s how, via command line arguments.

     -distance=200 : This will tell the robot to maintain a distance
of 200 centimeters from the nearest obstacle perceivable by the frontmost
sonar sensor. You can choose any reasonable value.
     -maxSpeed=20 : Change the default maximum speed to 20
centimeters per second (cm/sec) from the default to 30 cm/sec. You can
choose any reasonable value, but be sure it’s not too high.
     -limp=yes : This tells the robot to leave its motors in a "limp"
state, that is, movable by hand. This is useful for observing the calculated
velocities while moving the robot by hand. 

Now, fire up your new client program, simple:

 ./simple

The robot will apply the necessary velocity to maintain the distance (either the default distance, 100 cm, or the distance you specified on the command line) from the nearest obstacle perceivable by the frontmost sonar sensor. Experiment by moving this obstacle (which could be yourself!) closer to the robot, and then further away, noticing how simple recalculates the velocity based on new conditions. To stop your program, interrupt it with <CTRL-C> This calls commShutdown, halting operations and disconnecting your client program from the baseServer.

Once you have your test application working, try making a few simple modifications — one at a time — to experiment with different polling intervals, distances, maximum speeds, etc. Build on your test program, and on your knowledge. With a bit of experience, you’ll find you’ve gained a heightened awareness of your robot’s capabilities and an enhanced intuition for directing its behavior.

The Robot Challenge
Ready for a robot programming challenge? Looking at just the array of sonar sensors, maneuver your robot to the exact center of a room. For complete descriptions and call sequences for calls that will be useful in this exercise, see command descriptions in Chapter 4. Making The Robot Move. Here are some functions you might want to use: translateVelocityPos, translateVelocityNeg, translateRelativePos, translateRelativeNeg, rotateRelativePos, rotateRelativeNeg.

Previous Page Page Top TOC Index Next Page