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

ArAnalogGyro.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 #include "ariaOSDef.h"
00028 #include "ArCommands.h"
00029 #include "ArExport.h"
00030 #include "ArAnalogGyro.h"
00031 #include "ArRobot.h"
00032 #include "ArRobotConfigPacketReader.h"
00033 
00036 ArAnalogGyro::ArAnalogGyro(ArRobot *robot) : 
00037   myHandleGyroPacketCB(this, &ArAnalogGyro::handleGyroPacket),
00038   myEncoderCorrectCB(this, &ArAnalogGyro::encoderCorrect),
00039   myStabilizingCB(this, &ArAnalogGyro::stabilizingCallback)
00040 {
00041   myRobot = robot;
00042   myRobot->addPacketHandler(&myHandleGyroPacketCB);
00043   myRobot->addStabilizingCB(&myStabilizingCB);
00044   myRobot->setEncoderCorrectionCallback(&myEncoderCorrectCB);
00045   // this scaling factor now comes from the parameter file
00046   myScalingFactor = 0;
00047   myHeading = 0;
00048   myReadingThisCycle = false;
00049 
00050   myAverageTotal = 0;
00051   myAverageCount = 0;
00052   myLastAverageTaken.setSec(0);
00053   myLastAverageTaken.setMSec(0);
00054   myLastAverage = 0;
00055   // nominal values
00056   myGyroSigma = .01;
00057   myInertialVarianceModel = 0.001;
00058   myRotVarianceModel = .25; // deg2/deg
00059   myTransVarianceModel = 4.0; // deg2/meter
00060   myAccumulatedDelta = 0;
00061   myIsActive = true;
00062   myHaveGottenData = false;
00063   myLogAnomalies = false;
00064   if (myRobot->isConnected())
00065     stabilizingCallback();
00066 }
00067 
00068 ArAnalogGyro::~ArAnalogGyro()
00069 {
00070   myRobot->comInt(ArCommands::GYRO, 0);
00071   myRobot->remPacketHandler(&myHandleGyroPacketCB);
00072   myRobot->remStabilizingCB(&myStabilizingCB);
00073   myRobot->setEncoderCorrectionCallback(NULL);
00074 }
00075 
00076 void ArAnalogGyro::stabilizingCallback(void)
00077 {
00078   if (myRobot->getOrigRobotConfig() != NULL &&
00079       myRobot->getOrigRobotConfig()->getHasGyro() == 1)
00080   {
00081     myScalingFactor = myRobot->getRobotParams()->getGyroScaler();
00082     if (!myRobot->isConnected())
00083       ArLog::log(ArLog::Normal, "Stabilizing gyro");
00084     if (!myRobot->isConnected() && myRobot->getStabilizingTime() < 3000)
00085       myRobot->setStabilizingTime(3000);
00086     myRobot->comInt(ArCommands::GYRO, 1);
00087   }
00088 }
00089 
00090 bool ArAnalogGyro::handleGyroPacket(ArRobotPacket *packet)
00091 {
00092   int numReadings;
00093   int i;
00094   double reading;
00095   int temperature;
00096   double rate;
00097   ArTime now;
00098 
00099   if (packet->getID() != 0x98)
00100     return false;
00101 
00102   numReadings = packet->bufToByte();
00103   if (numReadings > 0)
00104     myHaveGottenData = true;
00105   //packet->log();
00106   //printf("%d readings %d bytes ", numReadings, packet->getLength() - packet->getReadLength());
00107   for (i = 0; i < numReadings; i++)
00108   {
00109     reading = packet->bufToByte2();
00110     temperature = packet->bufToUByte();
00111 
00112     // if we haven't moved, check our average, to see if we've moved,
00113     // we see if the average is within .5% of the average and
00114     // if the velocity is less then 1 mm / sec and 
00115     // if the rotational velocity is less then 1 deg / sec
00116     //printf("%d %g %g %g %g\n", myAverageCount, myAverageTotal / myAverageCount, reading, myRobot->getVel(), myRobot->getRotVel());
00117     if ((myAverageCount == 0 || fabs(myAverageTotal / myAverageCount - reading) < myAverageTotal / myAverageCount * .005) &&
00118         fabs(myRobot->getVel()) < 1 && 
00119         fabs(myRobot->getRotVel()) < 1)
00120     {
00121       if (myAverageStarted.mSecSince() > 1000 && myAverageCount > 25)
00122       {
00123         //printf("new average\n");
00124         myLastAverage = myAverageTotal / myAverageCount;
00125         myLastAverageTaken.setToNow();
00126         myAverageTotal = 0;
00127         myAverageCount = 0;
00128         myAverageStarted.setToNow();
00129       }
00130       myAverageTotal += reading;
00131       myAverageCount++;
00132     }
00133     else
00134     {
00135       myAverageTotal = 0;
00136       myAverageCount = 0;
00137       myAverageStarted.setToNow();
00138     }
00139     
00140     if (myLastAverage == 0)
00141       continue;
00142     reading -= myLastAverage;
00143     rate = ((reading * 5.0 / 1023)) * 300 / 2.5 * myScalingFactor;
00144     rate *= -1;
00145 
00146     myTemperature = temperature;
00147     //printf("reading %10f rate %10f diff %10f temp %d, ave %g\n", reading, rate, rate * .025, temperature, myLastAverage);
00148 
00149     // if we're not moving and the reading is small disregard it
00150     if ((fabs(myRobot->getVel()) < 2 && fabs(myRobot->getRotVel()) < 2) &&
00151         ArMath::fabs(reading) < 2)      
00152     {
00153       rate = 0;
00154     }
00155     myHeading += rate * .025;
00156     //printf("rate %6.3f, reading %6.3f heading %6.3f\n", rate, reading, myHeading);
00157 
00158     myHeading = ArMath::fixAngle(myHeading);
00159 
00160     if (myTimeLastPacket != time(NULL)) 
00161     {
00162       myTimeLastPacket = time(NULL);
00163       myPacCount = myPacCurrentCount;
00164       myPacCurrentCount = 0;
00165     }
00166     myPacCurrentCount++;
00167     myReadingThisCycle = true;
00168     //printf("(%3d %3d)", reading, temperature);
00169   }
00170   //printf("\n");
00171   return true;
00172 }
00173 
00174 double ArAnalogGyro::encoderCorrect(ArPoseWithTime deltaPose)
00175 {
00176   ArPose ret;
00177 
00178   // variables
00179   double inertialVariance;
00180   double encoderVariance;
00181 
00182   double robotDeltaTh;
00183   double inertialDeltaTh;
00184   double deltaTh;
00185 
00186   /*
00187   ArPose lastPose;
00188   double lastTh;
00189   ArPose thisPose;
00190   double thisTh;
00191   */
00192   ArPoseWithTime zero(0.0, 0.0, 0.0);
00193 
00194 
00195   // if we didn't get a reading this take what we got at face value
00196   if (!myReadingThisCycle)
00197   {
00198     //ArLog::log(ArLog::Verbose, "ArAnalogGyro: no inertial reading, using encoder");
00199     myAccumulatedDelta += deltaPose.getTh();
00200     //printf("adding %f\n", myAccumulatedDelta);
00201     return deltaPose.getTh();
00202   }
00203 
00204   // 6/20/05 MPL added this fix
00205   robotDeltaTh = ArMath::fixAngle(myAccumulatedDelta + deltaPose.getTh());
00206   //printf("using %f %f %f\n", robotDeltaTh, myAccumulatedDelta, deltaPose.getTh());
00207 
00208   inertialVariance = (myGyroSigma * myGyroSigma * 10);
00209   // was: deltaPose.getTime().mSecSince(myLastAsked)/10.0);
00210 
00211 
00212   //printf("@ %10f %10f %10f %10f\n", multiplier, ArMath::subAngle(thisTh, lastTh), thisTh, lastTh);
00213   inertialDeltaTh = ArMath::subAngle(myHeading, myLastHeading);
00214 
00215   inertialVariance += fabs(inertialDeltaTh) * myInertialVarianceModel;
00216   encoderVariance = (fabs(deltaPose.getTh()) * myRotVarianceModel +
00217                      deltaPose.findDistanceTo(zero) * myTransVarianceModel);
00218   
00219   
00220   if (myLogAnomalies)
00221   {
00222     if (fabs(inertialDeltaTh) < 1 && fabs(robotDeltaTh) < 1)
00223     {
00224 
00225     }
00226     else if (fabs(robotDeltaTh) < 1 && fabs(inertialDeltaTh) > 2)
00227       ArLog::log(ArLog::Normal, "ArAnalogGyro::anomaly: Gyro (%.1f) moved but encoder (%.1f) didn't, using gyro", inertialDeltaTh, robotDeltaTh);
00228     else if ((inertialDeltaTh < -1 && robotDeltaTh > 1) ||
00229              (robotDeltaTh < -1 && inertialDeltaTh > 1))
00230       ArLog::log(ArLog::Normal, "ArAnalogGyro::anomaly: gyro (%.1f) moved opposite of robot (%.1f)", inertialDeltaTh, robotDeltaTh);
00231     else if (fabs(robotDeltaTh) < fabs(inertialDeltaTh * .66666))
00232       ArLog::log(ArLog::Normal, "ArAnalogGyro::anomaly: robot (%.1f) moved less than gyro (%.1f)", robotDeltaTh, inertialDeltaTh);
00233     else if (fabs(inertialDeltaTh) < fabs(robotDeltaTh * .66666))
00234       ArLog::log(ArLog::Normal, "ArAnalogGyro::anomaly: gyro (%.1f) moved less than robot (%.1f)", inertialDeltaTh, robotDeltaTh);
00235   }
00236 
00237 
00238   //don't divide by 0, or close to it
00239   if (fabs(inertialVariance + encoderVariance) < .00000001)
00240     deltaTh = 0;
00241   // if we get no encoder readings, but we get gyro readings, just
00242   // believe the gyro (this case is new 6/20/05 MPL)
00243   else if (fabs(robotDeltaTh) < 1 && fabs(inertialDeltaTh) > 2)
00244     deltaTh = ArMath::fixAngle(inertialDeltaTh);
00245   else
00246     deltaTh = ArMath::fixAngle(
00247             (robotDeltaTh * 
00248              (inertialVariance / (inertialVariance + encoderVariance))) +
00249             (inertialDeltaTh *
00250              (encoderVariance / (inertialVariance + encoderVariance))));
00251 
00252   // now we need to compensate for the readings we got when we didn't
00253   // have gyro readings
00254   deltaTh -= myAccumulatedDelta;
00255   myReadingThisCycle = false;
00256   myLastHeading = myHeading;
00257   //printf("%6.3f %6.3f %6.3f\n", deltaTh, inertialDeltaTh, robotDeltaTh);
00258 
00259   myAccumulatedDelta = 0;
00260   
00261   if (myIsActive)
00262     return deltaTh;
00263   else
00264     return deltaPose.getTh();
00265 }
00266 
00267 
00268 void ArAnalogGyro::activate(void)
00269 { 
00270   if (!myIsActive)
00271     ArLog::log(ArLog::Normal, "Activating gyro"); 
00272   myIsActive = true; 
00273 }
00274 
00275 void ArAnalogGyro::deactivate(void)
00276 { 
00277   if (myIsActive)
00278     ArLog::log(ArLog::Normal, "Dectivating gyro"); 
00279   myIsActive = false; 
00280 }

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