00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdarg.h>
00028
00029 #include "ArExport.h"
00030 #include "ariaOSDef.h"
00031 #include "ArSickLogger.h"
00032 #include "ArRobot.h"
00033 #include "ArSick.h"
00034 #include "ArJoyHandler.h"
00035 #include "ariaInternal.h"
00036
00057 ArSickLogger::ArSickLogger(ArRobot *robot, ArSick *sick,
00058 double distDiff, double degDiff,
00059 const char *fileName, bool addGoals,
00060 ArJoyHandler *joyHandler,
00061 const char *baseDirectory) :
00062 mySectors(18),
00063 myTaskCB(this, &ArSickLogger::robotTask),
00064 myGoalKeyCB(this, &ArSickLogger::goalKeyCallback),
00065 myLoopPacketHandlerCB(this, &ArSickLogger::loopPacketHandler)
00066 {
00067 ArKeyHandler *keyHandler;
00068
00069 ArSick::Degrees degrees;
00070 ArSick::Increment increment;
00071 double deg, incr;
00072
00073 myOldReadings = false;
00074 myNewReadings = true;
00075 myWrote = false;
00076 myRobot = robot;
00077 mySick = sick;
00078 if (baseDirectory != NULL && strlen(baseDirectory) > 0)
00079 myBaseDirectory = baseDirectory;
00080 else
00081 myBaseDirectory = "";
00082 std::string realFileName;
00083 if (fileName[0] == '/' || fileName[0] == '\\')
00084 {
00085 realFileName = fileName;
00086 }
00087 else
00088 {
00089 realFileName = myBaseDirectory;
00090 realFileName += fileName;
00091 }
00092 myFileName = realFileName;
00093
00094 myFile = fopen(realFileName.c_str(), "w+");
00095 degrees = mySick->getDegrees();
00096 increment = mySick->getIncrement();
00097 if (degrees == ArSick::DEGREES180)
00098 deg = 180;
00099 else
00100 deg = 100;
00101 if (increment == ArSick::INCREMENT_ONE)
00102 incr = 1;
00103 else
00104 incr = .5;
00105 if (myFile != NULL)
00106 {
00107 const ArRobotParams *params;
00108 params = robot->getRobotParams();
00109 fprintf(myFile, "LaserOdometryLog\n");
00110 fprintf(myFile, "#Created by ARIA's ArSickLogger\n");
00111 fprintf(myFile, "version: 2\n");
00112 fprintf(myFile, "sick1pose: %d %d %.2f\n", params->getLaserX(),
00113 params->getLaserY(), params->getLaserTh());
00114 fprintf(myFile, "sick1conf: %d %d %d\n",
00115 ArMath::roundInt(0.0 - deg / 2.0),
00116 ArMath::roundInt(deg / 2.0), ArMath::roundInt(deg / incr + 1.0));
00117 }
00118 else
00119 ArLog::log(ArLog::Terse, "ArSickLogger cannot write to file %s",
00120 myFileName.c_str());
00121
00122 myDistDiff = distDiff;
00123 myDegDiff = degDiff;
00124 myFirstTaken = false;
00125 myScanNumber = 0;
00126 myLastVel = 0;
00127 myStartTime.setToNow();
00128 myRobot->addUserTask("Sick Logger", 1, &myTaskCB);
00129
00130 char uCFileName[15];
00131 strncpy(uCFileName, fileName, 14);
00132 uCFileName[14] = '\0';
00133 myRobot->comStr(94, uCFileName);
00134
00135 myRobot->addPacketHandler(&myLoopPacketHandlerCB);
00136
00137 myAddGoals = addGoals;
00138 myJoyHandler = joyHandler;
00139 myTakeReadingExplicit = false;
00140 myAddGoalExplicit = false;
00141 myAddGoalKeyboard = false;
00142 myFirstGoalTaken = false;
00143 myNumGoal = 1;
00144 myLastLoops = 0;
00145
00146 if (myAddGoals)
00147 {
00148
00149
00150 if ((keyHandler = Aria::getKeyHandler()) == NULL)
00151 {
00152 keyHandler = new ArKeyHandler;
00153 Aria::setKeyHandler(keyHandler);
00154 myRobot->attachKeyHandler(keyHandler);
00155 }
00156
00157
00158 if (!keyHandler->addKeyHandler('g', &myGoalKeyCB))
00159 ArLog::log(ArLog::Terse, "The key handler already has a key for g, sick logger goal handling will not work correctly.");
00160 if (!keyHandler->addKeyHandler('G', &myGoalKeyCB))
00161 ArLog::log(ArLog::Terse, "The key handler already has a key for g, sick logger goal handling will not work correctly.");
00162
00163
00164 }
00165
00166
00167 }
00168
00169 ArSickLogger::~ArSickLogger()
00170 {
00171 myRobot->remUserTask(&myTaskCB);
00172 myRobot->remPacketHandler(&myLoopPacketHandlerCB);
00173 myRobot->comStr(94, "");
00174 if (myFile != NULL)
00175 {
00176 fprintf(myFile, "# End of log\n");
00177 fclose(myFile);
00178 }
00179 }
00180
00181 bool ArSickLogger::loopPacketHandler(ArRobotPacket *packet)
00182 {
00183 unsigned char loops;
00184 if (packet->getID() != 0x96)
00185 return false;
00186 loops = packet->bufToUByte();
00187 unsigned char bit;
00188 int num;
00189 if (loops != myLastLoops)
00190 {
00191 for (bit = 1, num = 1; num <= 8; bit *= 2, num++)
00192 {
00193 if ((loops & bit) && !(myLastLoops & bit))
00194 {
00195 addTagToLog("loop: start %d", num);
00196 ArLog::log(ArLog::Normal, "Starting loop %d", num);
00197 }
00198 else if (!(loops & bit) && (myLastLoops & bit))
00199 {
00200 addTagToLog("loop: end %d", num);
00201 ArLog::log(ArLog::Normal, "Ending loop %d", num);
00202 }
00203 }
00204 }
00205 myLastLoops = loops;
00206 return true;
00207 }
00208
00217 void ArSickLogger::addTagToLogPlain(const char *str)
00218 {
00219 myTags.push_back(str);
00220 }
00221
00230 void ArSickLogger::addTagToLog(const char *str, ...)
00231 {
00232 char buf[2048];
00233 va_list ptr;
00234 va_start(ptr, str);
00235 vsprintf(buf, str, ptr);
00236 addTagToLogPlain(buf);
00237 va_end(ptr);
00238 }
00239
00240
00249 void ArSickLogger::addInfoToLogPlain(const char *str)
00250 {
00251 myInfos.push_back(str);
00252 }
00253
00261 void ArSickLogger::addInfoToLog(const char *str, ...)
00262 {
00263 char buf[2048];
00264 va_list ptr;
00265 va_start(ptr, str);
00266 vsprintf(buf, str, ptr);
00267 addInfoToLogPlain(buf);
00268 va_end(ptr);
00269 }
00270
00271 void ArSickLogger::goalKeyCallback(void)
00272 {
00273 myAddGoalKeyboard = true;
00274 }
00275
00276 void ArSickLogger::internalAddGoal(void)
00277 {
00278
00279
00280
00281 if (!myAddGoals && !myAddGoalExplicit)
00282 return;
00283
00284
00285 if (myRobot->isConnected() &&
00286 (!myFirstGoalTaken ||
00287 myAddGoalExplicit ||
00288 myLastGoalTakenPose.findDistanceTo(myRobot->getEncoderPose()) > 300 ||
00289 myLastGoalTakenPose.findAngleTo(myRobot->getEncoderPose()) > 90 ||
00290 myLastGoalTakenTime.secSince() > 10))
00291
00292 {
00293
00294
00295
00296
00297
00298 if ((myRobot->getFlags() & ArUtil::BIT9) ||
00299 myAddGoalKeyboard ||
00300 myAddGoalExplicit ||
00301 (myJoyHandler != NULL && (myJoyHandler->getButton(2) ||
00302 myJoyHandler->getButton(3) ||
00303 myJoyHandler->getButton(4))))
00304 {
00305 myFirstGoalTaken = true;
00306 myAddGoalExplicit = false;
00307 myLastGoalTakenTime.setToNow();
00308 myLastGoalTakenPose = myRobot->getEncoderPose();
00309
00310
00311 addTagToLog("cairn: GoalWithHeading \"\" ICON_GOALWITHHEADING \"goal%d\"", myNumGoal);
00312 printf("Goal %d taken\n", myNumGoal);
00313 myNumGoal++;
00314 }
00315 }
00316
00317
00318 myAddGoalKeyboard = false;
00319
00320 }
00321
00322 void ArSickLogger::internalWriteTags(void)
00323 {
00324 time_t msec;
00325
00326
00327 while (myInfos.size() > 0)
00328 {
00329 if (myFile != NULL)
00330 {
00331 myWrote = true;
00332 fprintf(myFile, "%s\n", (*myInfos.begin()).c_str());
00333 }
00334 myInfos.pop_front();
00335 }
00336
00337
00338
00339 while (myTags.size() > 0)
00340 {
00341 if (myFile != NULL)
00342 {
00343 myWrote = true;
00344 msec = myStartTime.mSecSince();
00345 fprintf(myFile, "time: %ld.%ld\n", msec / 1000, msec % 1000);
00346 internalPrintPos(myRobot->getEncoderPose());
00347 fprintf(myFile, "%s\n", (*myTags.begin()).c_str());
00348 }
00349 myTags.pop_front();
00350 }
00351 }
00352
00353 void ArSickLogger::internalTakeReading(void)
00354 {
00355 const std::list<ArSensorReading *> *readings;
00356 std::list<ArSensorReading *>::const_iterator it;
00357 std::list<ArSensorReading *>::const_reverse_iterator rit;
00358 ArPose poseTaken;
00359 time_t msec;
00360 ArSensorReading *reading;
00361
00362
00363
00364
00365
00366
00367
00368 if (myRobot->isConnected() && (!myFirstTaken || myTakeReadingExplicit ||
00369 myLast.findDistanceTo(myRobot->getEncoderPose()) > myDistDiff ||
00370 fabs(ArMath::subAngle(myLast.getTh(),
00371 myRobot->getEncoderPose().getTh())) > myDegDiff ||
00372 ((myLastVel < 0 && myRobot->getVel() > 0 ||
00373 myLastVel > 0 && myRobot->getVel() < 0) &&
00374 myLast.findDistanceTo(myRobot->getEncoderPose()) > 50)))
00375 {
00376 myWrote = true;
00377 mySick->lockDevice();
00378 readings = mySick->getRawReadings();
00379 if (readings == NULL || (it = readings->begin()) == readings->end() ||
00380 myFile == NULL)
00381 {
00382 mySick->unlockDevice();
00383 return;
00384 }
00385 myTakeReadingExplicit = false;
00386 myScanNumber++;
00387 ArLog::log(ArLog::Normal,
00388 "Taking a reading from the %d laser values",
00389 readings->size());
00390 myFirstTaken = true;
00391 myLast = myRobot->getEncoderPose();
00392 poseTaken = (*readings->begin())->getEncoderPoseTaken();
00393 myLastVel = myRobot->getVel();
00394 msec = myStartTime.mSecSince();
00395 fprintf(myFile, "#Scan %d\n", myScanNumber);
00396 fprintf(myFile, "time: %ld.%ld\n", msec / 1000, msec % 1000);
00397
00398
00399
00400 internalPrintPos(poseTaken);
00401
00402 if (myOldReadings)
00403 {
00404 fprintf(myFile, "sick1: ");
00405
00406 if (!mySick->isLaserFlipped())
00407 {
00408
00409 for (it = readings->begin(); it != readings->end(); it++)
00410 {
00411 reading = (*it);
00412 fprintf(myFile, "%d ", reading->getRange());
00413 }
00414 }
00415 else
00416 {
00417 for (rit = readings->rbegin(); rit != readings->rend(); rit++)
00418 {
00419 reading = (*rit);
00420 fprintf(myFile, "%d ", reading->getRange());
00421 }
00422 }
00423 fprintf(myFile, "\n");
00424 }
00425 if (myNewReadings)
00426 {
00427 fprintf(myFile, "scan1: ");
00428
00429 if (!mySick->isLaserFlipped())
00430 {
00431
00432 for (it = readings->begin(); it != readings->end(); it++)
00433 {
00434 reading = (*it);
00435 if (!reading->getIgnoreThisReading())
00436 fprintf(myFile, "%.0f %.0f ",
00437 reading->getLocalX() - mySick->getSensorPositionX(),
00438 reading->getLocalY() - mySick->getSensorPositionY());
00439 else
00440 fprintf(myFile, "0 0 ");
00441 }
00442 }
00443 else
00444 {
00445 for (rit = readings->rbegin(); rit != readings->rend(); rit++)
00446 {
00447 reading = (*rit);
00448 if (!reading->getIgnoreThisReading())
00449 fprintf(myFile, "%.0f %.0f ",
00450 reading->getLocalX() - mySick->getSensorPositionX(),
00451 reading->getLocalY() - mySick->getSensorPositionY());
00452 else
00453 fprintf(myFile, "0 0 ");
00454 }
00455 }
00456 fprintf(myFile, "\n");
00457 }
00458 mySick->unlockDevice();
00459 }
00460 }
00461
00462 void ArSickLogger::internalPrintPos(ArPose poseTaken)
00463 {
00464 if (myFile == NULL)
00465 return;
00466 ArPose encoderPose = myRobot->getEncoderPose();
00467 ArPose rawEncoderPose = myRobot->getRawEncoderPose();
00468 ArTransform normalToRaw(rawEncoderPose, encoderPose);
00469
00470 ArPose rawPose;
00471 rawPose = normalToRaw.doInvTransform(poseTaken);
00472 fprintf(myFile, "#rawRobot: %.0f %.0f %.2f %.0f %.0f\n",
00473 rawPose.getX(),
00474 rawPose.getY(),
00475 rawPose.getTh(),
00476 myRobot->getVel(),
00477 myRobot->getRotVel());
00478 fprintf(myFile, "robot: %.0f %.0f %.2f %.0f %.0f\n",
00479 poseTaken.getX(),
00480 poseTaken.getY(),
00481 poseTaken.getTh(),
00482 myRobot->getVel(),
00483 myRobot->getRotVel());
00484 }
00485
00486 void ArSickLogger::robotTask(void)
00487 {
00488
00489
00490 internalAddGoal();
00491
00492
00493 internalWriteTags();
00494
00495
00496 internalTakeReading();
00497
00498
00499 if (myWrote)
00500 {
00501 fflush(myFile);
00502 #ifndef WIN32
00503 fsync(fileno(myFile));
00504 #endif
00505 }
00506 myWrote = false;
00507 }
00508
00509
00510
00511