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

wanderAndLogData.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 #include "Aria.h"
00027 #include <string>
00028 
00029 /*
00030  * This is useful as a diagnostic tool, plus it shows all the many accessor
00031  * methods of ArRobot for robot state. It makes the robot wander, using sonar
00032  * to avoid obstacles, and prints out various pieces of robot state information
00033  * each second. Refer to the ARIA ArRobot documentation and to your robot manual
00034  * (section on standard ARCOS SIP packet contents) for details on the data.
00035  */
00036 
00037 
00038 
00039 /* function to display a byte as a string of 8 '1' and '0' characters. */
00040 std::string byte_as_bitstring(char byte) 
00041 {
00042   char tmp[9];
00043   int bit; 
00044   int ch;
00045   for(bit = 7, ch = 0; bit >= 0; bit--,ch++)
00046     tmp[ch] = ((byte>>bit)&1) ? '1' : '0';
00047   tmp[8] = 0;
00048   return std::string(tmp);
00049 }
00050 
00051 /* function to display a 2-byte int as a string of 16 '1' and '0' characters. */
00052 std::string int_as_bitstring(ArTypes::Byte2 n) 
00053 {
00054   char tmp[17];
00055   int bit;
00056   int ch;
00057   for(bit = 15, ch = 0; bit >= 0; bit--, ch++)
00058     tmp[ch] = ((n>>bit)&1) ? '1' : '0';
00059   tmp[16] = 0;
00060   return std::string(tmp);
00061 }
00062 
00063 /* Some events might only be detectable in one robot cycle, not over the
00064  * 1-second period that the main thread sleeps. This cycle callback will detect
00065  * those and save them in some global variables. */
00066 bool wasLeftMotorStalled = false;
00067 bool wasRightMotorStalled = false;
00068 ArTypes::UByte2 cumulativeStallVal = 0;
00069 ArTypes::UByte2 cumulativeRobotFlags = 0;
00070 bool wasLeftIRTriggered = false;
00071 bool wasRightIRTriggered = false;
00072 bool wasEStopTriggered = false;
00073 
00074 bool cycleCallback(ArRobot* robot)
00075 {
00076   cumulativeStallVal |= robot->getStallValue();
00077   wasLeftMotorStalled = wasLeftMotorStalled || robot->isLeftMotorStalled();
00078   wasRightMotorStalled = wasRightMotorStalled || robot->isRightMotorStalled();
00079   wasEStopTriggered = wasEStopTriggered || robot->getEstop();
00080   wasLeftIRTriggered = wasLeftIRTriggered || (robot->hasTableSensingIR() && robot->isLeftTableSensingIRTriggered());
00081   wasRightIRTriggered = wasRightIRTriggered || (robot->hasTableSensingIR() && robot->isRightTableSensingIRTriggered());
00082   return true;
00083 }
00084 
00085 
00086 /* main function */
00087 int main(int argc, char **argv)
00088 {
00089   // robot and devices
00090   ArRobot robot;
00091   ArSonarDevice sonar;
00092   ArBumpers bumpers;
00093   ArIRs ir;
00094 
00095   // the actions we'll use to wander and avoid obstacles
00096   ArActionStallRecover recoverAct;
00097   ArActionBumpers bumpAct;
00098   ArActionAvoidFront avoidFrontNearAct("Avoid Front Near", 225, 0);
00099   ArActionAvoidFront avoidFrontFarAct;
00100   ArActionConstantVelocity constantVelocityAct("Constant Velocity", 400);
00101 
00102   // initialize aria and aria's logging destination and level
00103   Aria::init();
00104   ArLog::init(ArLog::StdErr, ArLog::Normal);
00105 
00106   // connector
00107   ArSimpleConnector connector(&argc, argv);
00108   if (!connector.parseArgs() || argc > 1)
00109   {
00110     connector.logOptions();
00111     exit(1);
00112   }
00113 
00114   printf("This program will make the robot wander around, avoiding obstacles, and print some data and events.\nPress Ctrl-C to exit.\n");
00115   
00116   // add the range devices to the robot
00117   robot.addRangeDevice(&sonar);
00118   robot.addRangeDevice(&bumpers);
00119   robot.addRangeDevice(&ir);
00120   
00121   // try to connect, if we fail exit
00122   if (!connector.connectRobot(&robot))
00123   {
00124     printf("Could not connect to robot... exiting\n");
00125     Aria::shutdown();
00126     return 1;
00127   }
00128 
00129   // turn on the motors, turn off amigobot sound effects (for old h8-model amigobots)
00130   robot.enableMotors();
00131   robot.comInt(ArCommands::SOUNDTOG, 0);
00132 
00133   // add the actions created above
00134   robot.addAction(&recoverAct, 100);
00135   robot.addAction(&bumpAct, 75);
00136   robot.addAction(&avoidFrontNearAct, 50);
00137   robot.addAction(&avoidFrontFarAct, 49);
00138   robot.addAction(&constantVelocityAct, 25);
00139 
00140   // Cycle callback to check for events
00141   robot.addUserTask("checkevents", 1, new ArGlobalRetFunctor1<bool, ArRobot*>(&cycleCallback, &robot));
00142 
00143   // start the robot running, true means that if we lose robot connection the 
00144   // ArRobot runloop stops
00145   robot.runAsync(true);
00146   
00147   // Print data header
00148 #define HEADFORMAT "%-24s %-5s %-16s %-5s %-6s %-6s %-16s %-8s %-8s %-8s %-8s %-8s %-8s %-10s %-10s %-5s %-5s %s"
00149 #define DATAFORMAT "%-24s %03.02f %-16s %-5s %-6s %-6s %-16s %-8d %-8d %-8g %-8g %-8s %-8s %-10lu %-10lu %-5s %-5s" // doesn't include bumps details on end
00150   printf("\n" HEADFORMAT "\n\n",
00151         "Time",
00152         "Volts",
00153         "Flags",
00154         "EStop",
00155         "StallL",
00156         "StallR",
00157         "StallVal",
00158         "#SIP/sec",
00159         "#Son/sec",
00160         "Vel L",
00161         "Vel R",
00162         "DigIns",
00163         "DigOuts",
00164         "Enc L",
00165         "Enc R",
00166         "IR L",
00167         "IR R",
00168         "Cur Bumps, (Last Bump Pose)"
00169     );
00170 
00171   // Request that we will want encoder data
00172   robot.requestEncoderPackets();
00173 
00174   // Print data every second
00175   char timestamp[24];
00176   while(robot.isRunning()) {
00177     robot.lock();
00178     time_t t = time(NULL);
00179     strftime(timestamp, 24, "%Y-%m-%d %H:%M:%S", localtime(&t));
00180     printf( DATAFORMAT,
00181         timestamp,
00182         robot.getRealBatteryVoltage(),
00183         int_as_bitstring(cumulativeRobotFlags).c_str(),
00184         (wasEStopTriggered ? "YES" : "   "),
00185         (wasLeftMotorStalled?"YES":"   "), 
00186         (wasRightMotorStalled?"YES":"   "),
00187         int_as_bitstring(cumulativeStallVal).c_str(),
00188         robot.getMotorPacCount(),
00189         robot.getSonarPacCount(),
00190         robot.getLeftVel(), 
00191         robot.getRightVel(),
00192         byte_as_bitstring(robot.getDigIn()).c_str(),
00193         byte_as_bitstring(robot.getDigOut()).c_str(),
00194         robot.getLeftEncoder(),
00195         robot.getRightEncoder(),
00196         wasLeftIRTriggered?"YES": "   ",
00197         wasRightIRTriggered?"YES":"   "
00198       );
00199 
00200     // list indices of bumpers flaged in stallval
00201     // skip the last bit which is a motor stall flag
00202     ArTypes::UByte2 bumpmask = ArUtil::BIT15;
00203     int bump = 0;
00204     for(int bit = 16; bit > 0; bit--) 
00205     {
00206       if(bit == 9) // this is also a motor stall bit
00207       {
00208         bumpmask = bumpmask >> 1; 
00209         bit--;
00210         continue;
00211       }
00212       //printf("\n\tComparing stallval=%s to bumpmask=%s... ", int_as_bitstring(stallval).c_str(), int_as_bitstring(bumpmask).c_str());
00213       if(cumulativeStallVal & bumpmask)
00214         printf("%d ", bump);
00215       bumpmask = bumpmask >> 1;
00216       bump++;
00217     }
00218 
00219     // print pose of last bump sensor reading
00220     const std::list<ArPoseWithTime*>* bumpsensed = bumpers.getCurrentBuffer();
00221     if(bumpsensed)
00222     {
00223       //printf("%d readings. ", bumpsensed->size());
00224       if(bumpsensed->size() > 0 && bumpsensed->front()) {
00225         printf("(%.0f,%.0f)", bumpsensed->front()->getX(), bumpsensed->front()->getY());
00226       }
00227     }
00228     puts("");
00229 
00230     // clear events to accumulate for the next second
00231     cumulativeRobotFlags = cumulativeStallVal = 0;
00232     wasLeftMotorStalled = wasRightMotorStalled = wasLeftIRTriggered = wasRightIRTriggered = wasEStopTriggered = false;
00233 
00234     robot.unlock();
00235     ArUtil::sleep(1000);
00236   }
00237   
00238   // robot cycle stopped, probably because of lost robot connection
00239   Aria::shutdown();
00240   return 0;
00241 }

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