Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages | Examples

actsColorFollowingExample.cpp

00001 /*
00002 MobileRobots Advanced Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004, 2005 ActivMedia Robotics LLC
00004 Copyright (C) 2006, 2007 MobileRobots Inc.
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 MobileRobots for information about a commercial version of ARIA at 
00022 robots@mobilerobots.com or 
00023 MobileRobots Inc, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 */
00025 
00026 
00032 #include "Aria.h"
00033 
00034 
00035 
00036 // Chase is an action that moves the robot toward the largest blob that
00037 // appears in it's current field of view.
00038 class Chase : public ArAction
00039 {
00040   
00041 public:
00042   
00043   // The state of the chase action
00044   enum State {
00045     NO_TARGET,      // There is no target in view
00046     TARGET,         // This is a target in view
00047   };
00048 
00049   // Constructor
00050   Chase(ArACTS_1_2 *acts, ArVCC4 *camera);
00051   
00052   // Destructor
00053   ~Chase(void);
00054   
00055   // The action
00056   ArActionDesired *fire(ArActionDesired currentDesired);
00057 
00058   // Set the ACTS channel that we want to get blob info from
00059   bool setChannel(int channel);
00060 
00061   // Return the current state of this action
00062   State getState(void) { return myState; }
00063 
00064   // Height and width of pixels from frame-grabber
00065   enum {
00066     WIDTH = 160,
00067     HEIGHT = 120
00068   };
00069 
00070 protected:
00071   ArActionDesired myDesired;
00072   ArACTS_1_2 *myActs;
00073   ArVCC4 *myCamera;
00074   ArTime myLastSeen;
00075   State myState;
00076   int myChannel;
00077   int myMaxTime;
00078 };
00079 
00080 
00081 // Constructor: Initialize the chase action
00082 Chase::Chase(ArACTS_1_2 *acts, ArVCC4 *camera) :
00083     ArAction("Chase", "Chases the largest blob.")
00084 {
00085   myActs = acts;
00086   myCamera = camera;
00087   myChannel = 0;
00088   myState = NO_TARGET;
00089   setChannel(1);
00090   myLastSeen.setToNow();
00091   myMaxTime = 1000;
00092 }
00093 
00094 // Destructor
00095 Chase::~Chase(void) {}
00096 
00097 
00098 // The chase action
00099 ArActionDesired *Chase::fire(ArActionDesired currentDesired)
00100 {
00101   ArACTSBlob blob;
00102   ArACTSBlob largestBlob;
00103 
00104   bool flag = false;
00105 
00106   int numberOfBlobs;
00107   int blobArea = 10;
00108 
00109   double xRel, yRel;
00110 
00111   // Reset the desired action
00112   myDesired.reset();
00113   
00114   numberOfBlobs = myActs->getNumBlobs(myChannel);
00115 
00116   // If there are blobs to be seen, set the time to now
00117   if(numberOfBlobs != 0)
00118     {
00119       for(int i = 0; i < numberOfBlobs; i++)
00120     {
00121       myActs->getBlob(myChannel, i + 1, &blob);
00122       if(blob.getArea() > blobArea)
00123         {
00124           flag = true;
00125           blobArea = blob.getArea();
00126               largestBlob = blob;
00127         }
00128     }
00129 
00130       myLastSeen.setToNow();
00131     }
00132 
00133   // If we have not seen a blob in a while...
00134   if (myLastSeen.mSecSince() > myMaxTime)
00135     {
00136       if(myState != NO_TARGET) ArLog::log(ArLog::Normal, "Target Lost");
00137       myState = NO_TARGET;
00138     }
00139   else
00140     {
00141       // If we see a blob and haven't seen one before..
00142       if(myState != TARGET) ArLog::log(ArLog::Normal, "Target Aquired");
00143       myState = TARGET;
00144     }
00145 
00146   if(TARGET && flag == true)
00147     { 
00148       // Determine where the largest blob's center of gravity
00149       // is relative to the center of the camera
00150       xRel = (double)(largestBlob.getXCG() - WIDTH/2.0)  / (double)WIDTH;
00151       yRel = (double)(largestBlob.getYCG() - HEIGHT/2.0) / (double)HEIGHT;
00152       
00153       // Tilt the camera toward the blob
00154       if(!(ArMath::fabs(yRel) < .20))
00155     {
00156       if (-yRel > 0)
00157         myCamera->tiltRel(1);
00158       else
00159         myCamera->tiltRel(-1);
00160     }
00161 
00162       // Set the heading and velocity for the robot
00163       if (ArMath::fabs(xRel) < .10)
00164     {
00165       myDesired.setDeltaHeading(0);
00166     }
00167       else
00168     {
00169       if (ArMath::fabs(-xRel * 10) <= 10)
00170         myDesired.setDeltaHeading(-xRel * 10);
00171       else if (-xRel > 0)
00172         myDesired.setDeltaHeading(10);
00173       else
00174         myDesired.setDeltaHeading(-10);
00175      
00176     }
00177 
00178       myDesired.setVel(200);
00179       return &myDesired;    
00180     }
00181   else
00182     {
00183       myDesired.setVel(0);
00184       myDesired.setDeltaHeading(0);
00185       return &myDesired;
00186     }
00187 }
00188 
00189 // Set the channel that the blob info will be obtained from
00190 bool Chase::setChannel(int channel)
00191 {
00192   if (channel >= 1 && channel <= ArACTS_1_2::NUM_CHANNELS)
00193   {
00194     myChannel = channel;
00195     return true;
00196   }
00197   else
00198     return false;
00199 }
00200 
00201 
00202 
00203 
00204 
00205 
00206 
00207 // Main function
00208 int main(int argc, char** argv)
00209 {
00210   Aria::init();
00211 
00212   // The robot
00213   ArRobot robot;
00214 
00215   // A key handler to take input from keyboard
00216   ArKeyHandler keyHandler;
00217 
00218   // Sonar for basic obstacle avoidance
00219   ArSonarDevice sonar;
00220 
00221   // The camera (Cannon VC-C4)
00222   ArVCC4 vcc4 (&robot);
00223 
00224   // ACTS, for tracking blobs of color
00225   ArACTS_1_2 acts;
00226 
00227   // command line arguments
00228   ArArgumentParser argParser(&argc, argv);
00229   argParser.loadDefaultArguments();
00230   
00231   // The simple way to connect to things (takes arguments from argParser)
00232   ArSimpleConnector simpleConnector(&argParser);
00233 
00234   // Parse the arguments                
00235   if (!Aria::parseArgs())
00236   {    
00237     Aria::logOptions();
00238     keyHandler.restore();
00239     Aria::shutdown();
00240     return 1;
00241   }
00242 
00243   // Robot motion limiter actions (if obstacles are detected by sonar)
00244   ArActionLimiterForwards limiter("speed limiter near", 300, 600, 250);
00245   ArActionLimiterForwards limiterFar("speed limiter far", 300, 1100, 400);
00246   ArActionLimiterBackwards backwardsLimiter;
00247   ArActionConstantVelocity stop("stop", 0);
00248   ArActionConstantVelocity backup("backup", -200);
00249 
00250   // The color following action, defined above
00251   Chase chase(&acts, &vcc4);
00252 
00253   // Let Aria know about the key handler
00254   Aria::setKeyHandler(&keyHandler);
00255 
00256   // Add the key handler to the robot
00257   robot.attachKeyHandler(&keyHandler);
00258 
00259   // Add the sonar to the robot
00260   robot.addRangeDevice(&sonar);
00261 
00262   // Connect to the robot
00263   if (!simpleConnector.connectRobot(&robot))
00264   {
00265     printf("Could not connect to robot... exiting\n");
00266     keyHandler.restore();
00267     Aria::shutdown();
00268     return 1;
00269   }
00270 
00271   // Open a connection to ACTS
00272   acts.openPort(&robot);
00273 
00274   // Initialize the camera
00275   vcc4.init();
00276 
00277   // Wait a second.....
00278   ArUtil::sleep(1000);
00279 
00280   // Artificially keep the robot from going too fast
00281   robot.setAbsoluteMaxTransVel(400);
00282 
00283   // Enable the motors
00284   robot.comInt(ArCommands::ENABLE, 1);
00285   
00286   // Turn off the amigobot sounds
00287   robot.comInt(ArCommands::SOUNDTOG, 0);
00288 
00289   // Wait....
00290   ArUtil::sleep(200);
00291 
00292   // Add the actions to the robot in descending order of importance.
00293   robot.addAction(&limiter, 100);
00294   robot.addAction(&limiterFar, 99);
00295   robot.addAction(&backwardsLimiter, 98);
00296   robot.addAction(&chase, 77);
00297   robot.addAction(&backup, 50);
00298   robot.addAction(&stop, 30);
00299 
00300   // Run the robot processing cycle until the connection is lost
00301   robot.run(true);
00302   
00303   Aria::shutdown();
00304   return 0;
00305 }

Generated on Tue Feb 20 10:51:38 2007 for Aria by  doxygen 1.4.0