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

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

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