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

ArActionColorFollow.cpp

00001 /*
00002 ActivMedia Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004,2005 ActivMedia Robotics, LLC
00004 
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 ActivMedia Robotics for information about a commercial version of ARIA at 
00022 robots@activmedia.com or 
00023 ActivMedia Robotics, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 
00025 */
00026 
00027 
00028 #include "ArExport.h"
00029 
00030 #include "ariaOSDef.h"
00031 #include "ArActionColorFollow.h"
00032 #include "ArResolver.h"
00033 #include "ArRobot.h"
00034 
00035 // Constructor: Initialize the color follow action
00036 ArActionColorFollow::ArActionColorFollow(const char *name, ArACTS_1_2 *acts, 
00037                                                   ArPTZ *camera, double speed, 
00038                                                   int width, int height) :
00039     ArAction(name, "Follows the largest blob of color.")
00040 {
00041   myActs = acts;
00042   myAcquire = true;
00043   killMovement = true;
00044   myCamera = camera;
00045   myChannel = 0;
00046   myState = NO_TARGET;
00047   myMove = STOPPED;
00048   myLocation = CENTER;
00049   setChannel(1);
00050   myMaxTime = 2000;
00051   myWidth = width;
00052   myHeight = height;
00053   mySpeed = speed;
00054 }
00055 
00056 // Destructor
00057 ArActionColorFollow::~ArActionColorFollow(void) {}
00058 
00059 
00060 // The color follow action
00061 ArActionDesired *ArActionColorFollow::fire(ArActionDesired currentDesired)
00062 {
00063   ArACTSBlob blob;
00064   ArACTSBlob largestBlob;
00065 
00066   bool haveBlob = false;
00067 
00068   int numberOfBlobs;
00069   int blobArea = 20;
00070 
00071   double xRel, yRel;
00072 
00073   // Reset the desired action
00074   myDesired.reset();
00075 
00076   // If we are in fact connected to ACTS...
00077   if(myActs != NULL)
00078     {
00079       numberOfBlobs = myActs->getNumBlobs(myChannel);
00080       
00081       // If there are blobs to be seen, set the time to now
00082       if(numberOfBlobs != 0)
00083         {
00084           // Find the largest blob
00085           for(int i = 0; i < numberOfBlobs; i++)
00086             {
00087               myActs->getBlob(myChannel, i + 1, &blob);
00088               if(blob.getArea() > blobArea)
00089                 {
00090                   haveBlob = true;
00091                   blobArea = blob.getArea();
00092                   largestBlob = blob;
00093                 }
00094             }
00095           
00096           myLastSeen.setToNow();
00097         }
00098     
00099       // Decide the state of myState: do we have a target or not
00100       if (myLastSeen.mSecSince() > myMaxTime)
00101         {
00102           myState = NO_TARGET;
00103         }
00104       else
00105         {
00106           myState = TARGET;
00107         }
00108       
00109       // If we have a target start following
00110       if(myState == TARGET) myMove = FOLLOWING;
00111       // If not and we are allowed to acquire one, start searching
00112       else if(myState == NO_TARGET && myAcquire)
00113         {
00114           myMove = ACQUIRING;
00115         }
00116       // Otherwise stay still
00117       else myMove = STOPPED;
00118     }
00119 
00120   // We are not connected to acts, dont do anything
00121   else
00122     {
00123       myState = NO_TARGET;
00124       myMove = STOPPED;
00125     }
00126 
00127   // If we are following a blob of color
00128   if(myMove == FOLLOWING)
00129     {
00130       if(haveBlob)
00131         { 
00132           // Determine where the largest blob's center of gravity
00133           // is relative to the center of the camera
00134           xRel = (double)(largestBlob.getXCG() - myWidth/2.0)  / (double)myWidth;
00135           yRel = (double)(largestBlob.getYCG() - myHeight/2.0) / (double)myHeight;
00136           
00137           // Tilt the camera toward the blob
00138           if(!(ArMath::fabs(yRel) < .20) && myCamera != NULL)
00139             {
00140               if (-yRel > 0)
00141                 myCamera->tiltRel(1);
00142               else
00143                 myCamera->tiltRel(-1);
00144             }
00145 
00146           // If we can move, move after that blob
00147           if(!killMovement)
00148             {
00149               // Set the heading and velocity for the robot
00150               if (ArMath::fabs(xRel) < .10)
00151                 {
00152                   myLocation = CENTER;
00153                   myDesired.setDeltaHeading(0);
00154                   myDesired.setVel(mySpeed);
00155                   return &myDesired;
00156                 }
00157               else
00158                 {
00159                   if (ArMath::fabs(-xRel * 10) <= 10)
00160                     {
00161                       if(xRel < 0) myLocation = RIGHT;
00162                       if(xRel > 0) myLocation = LEFT;
00163                       myDesired.setDeltaHeading(-xRel * 10);
00164                     }
00165                   else if (-xRel > 0)
00166                     {
00167                       myLocation = RIGHT;
00168                       myDesired.setDeltaHeading(10);
00169                     }
00170                   else
00171                     {
00172                       myLocation = LEFT;
00173                       myDesired.setDeltaHeading(-10);
00174                     }
00175                   
00176                   myDesired.setVel(mySpeed);
00177                   return &myDesired;    
00178                 }
00179             }
00180         }
00181       // If we do not have a blob in sight, yet are still
00182       // supposed to be following one... 
00183       else if(!killMovement)
00184         {
00185           // head toward where the blob was last seen
00186           if(myLocation == LEFT)
00187             {
00188               myDesired.setDeltaHeading(-10);
00189               myDesired.setVel(0);
00190             }
00191           if(myLocation == RIGHT)
00192             {
00193               myDesired.setDeltaHeading(10);
00194               myDesired.setVel(0);
00195             }
00196           if(myLocation == CENTER)
00197             {
00198               myDesired.setDeltaHeading(0);
00199               myDesired.setVel(mySpeed);
00200             }
00201         
00202           return &myDesired; 
00203         }
00204     }
00205   // If we are acquiring, keep turning around in a circle
00206   else if(myMove == ACQUIRING)
00207     {
00208       if(myCamera != NULL) myCamera->tilt(0);
00209 
00210       if (!killMovement)
00211         {
00212           myDesired.setVel(0);
00213           myDesired.setDeltaHeading(8);
00214           return &myDesired;
00215         }
00216     }
00217   
00218   // If we dont meet one of the above conditions, just sit tight
00219   myDesired.setVel(0);
00220   myDesired.setDeltaHeading(0);
00221   return &myDesired;
00222 }
00223 
00224 // Set the channel that the blob info will be obtained from
00225 bool ArActionColorFollow::setChannel(int channel)
00226 {
00227   // Make sure that the requested channel is in range
00228   if (channel >= 1 && channel <= ArACTS_1_2::NUM_CHANNELS)
00229   {
00230     myChannel = channel;
00231     return true;
00232   }
00233   else
00234     return false;
00235 }
00236 
00237 // Set the camera that we are controlling
00238 void ArActionColorFollow::setCamera(ArPTZ *camera)
00239 {
00240   myCamera = camera;
00241 }
00242 
00243 // Toggle whether or not we should attempt to acquire a
00244 // target or just stay still
00245 void ArActionColorFollow::setAcquire(bool acquire)
00246 {
00247   myAcquire = acquire;
00248 }
00249 
00250 // Kill movement
00251 void ArActionColorFollow::stopMovement(void)
00252 {
00253   killMovement = true;
00254 }
00255 
00256 // Start moving
00257 void ArActionColorFollow::startMovement(void)
00258 {
00259   killMovement = false;
00260 }
00261 
00262 // Return the channel that we are looking on
00263 int ArActionColorFollow::getChannel(void)
00264 {
00265   return myChannel;
00266 }
00267 
00268 // Return if we are actively trying to find a blob
00269 // if one cannot be seen
00270 bool ArActionColorFollow::getAcquire(void)
00271 {
00272   return myAcquire;
00273 }
00274 
00275 // Return whether we are supposed to be moving or not
00276 bool ArActionColorFollow::getMovement(void)
00277 {
00278   return !killMovement;
00279 }
00280 
00281 // Return whether we can see a target or not
00282 bool ArActionColorFollow::getBlob(void)
00283 {
00284   if(myState == TARGET) return true;
00285   else return false;
00286 }

Generated on Wed Oct 19 12:56:34 2005 for Aria by  doxygen 1.4.0