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 #include <stdarg.h>
00027
00028 #include "ArExport.h"
00029 #include "ariaOSDef.h"
00030 #include "ArSickLogger.h"
00031 #include "ArRobot.h"
00032 #include "ArSick.h"
00033 #include "ArJoyHandler.h"
00034 #include "ArRobotJoyHandler.h"
00035 #include "ariaInternal.h"
00036
00057 AREXPORT 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 bool useReflectorValues,
00063 ArRobotJoyHandler *robotJoyHandler) :
00064 mySectors(18),
00065 myTaskCB(this, &ArSickLogger::robotTask),
00066 myGoalKeyCB(this, &ArSickLogger::goalKeyCallback),
00067 myLoopPacketHandlerCB(this, &ArSickLogger::loopPacketHandler)
00068 {
00069 ArKeyHandler *keyHandler;
00070
00071 ArSick::Degrees degrees;
00072 ArSick::Increment increment;
00073 double deg, incr;
00074
00075 myOldReadings = false;
00076 myNewReadings = true;
00077 myUseReflectorValues = useReflectorValues;
00078 myWrote = false;
00079 myRobot = robot;
00080 mySick = sick;
00081 if (baseDirectory != NULL && strlen(baseDirectory) > 0)
00082 myBaseDirectory = baseDirectory;
00083 else
00084 myBaseDirectory = "";
00085 std::string realFileName;
00086 if (fileName[0] == '/' || fileName[0] == '\\')
00087 {
00088 realFileName = fileName;
00089 }
00090 else
00091 {
00092 realFileName = myBaseDirectory;
00093 realFileName += fileName;
00094 }
00095 myFileName = realFileName;
00096
00097 myFile = fopen(realFileName.c_str(), "w+");
00098 degrees = mySick->getDegrees();
00099 increment = mySick->getIncrement();
00100 if (degrees == ArSick::DEGREES180)
00101 deg = 180;
00102 else
00103 deg = 100;
00104 if (increment == ArSick::INCREMENT_ONE)
00105 incr = 1;
00106 else
00107 incr = .5;
00108 if (myFile != NULL)
00109 {
00110 const ArRobotParams *params;
00111 params = robot->getRobotParams();
00112 fprintf(myFile, "LaserOdometryLog\n");
00113 fprintf(myFile, "#Created by ARIA's ArSickLogger\n");
00114 fprintf(myFile, "version: 2\n");
00115 fprintf(myFile, "sick1pose: %d %d %.2f\n", params->getLaserX(),
00116 params->getLaserY(), params->getLaserTh());
00117 fprintf(myFile, "sick1conf: %d %d %d\n",
00118 ArMath::roundInt(0.0 - deg / 2.0),
00119 ArMath::roundInt(deg / 2.0), ArMath::roundInt(deg / incr + 1.0));
00120 }
00121 else
00122 ArLog::log(ArLog::Terse, "ArSickLogger cannot write to file %s",
00123 myFileName.c_str());
00124
00125 myDistDiff = distDiff;
00126 myDegDiff = degDiff;
00127 myFirstTaken = false;
00128 myScanNumber = 0;
00129 myLastVel = 0;
00130 myStartTime.setToNow();
00131 myRobot->addUserTask("Sick Logger", 1, &myTaskCB);
00132
00133 char uCFileName[15];
00134 strncpy(uCFileName, fileName, 14);
00135 uCFileName[14] = '\0';
00136 myRobot->comStr(94, uCFileName);
00137
00138 myLoopPacketHandlerCB.setName("ArSickLogger");
00139 myRobot->addPacketHandler(&myLoopPacketHandlerCB);
00140
00141 myAddGoals = addGoals;
00142 myJoyHandler = joyHandler;
00143 myRobotJoyHandler = robotJoyHandler;
00144 myTakeReadingExplicit = false;
00145 myAddGoalExplicit = false;
00146 myAddGoalKeyboard = false;
00147 myLastAddGoalKeyboard = false;
00148 myLastJoyButton = false;
00149 myLastRobotJoyButton = false;
00150 myFirstGoalTaken = false;
00151 myNumGoal = 1;
00152 myLastLoops = 0;
00153
00154 if (myAddGoals && (keyHandler = Aria::getKeyHandler()) != NULL)
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 AREXPORT ArSickLogger::~ArSickLogger()
00166 {
00167 myRobot->remUserTask(&myTaskCB);
00168 myRobot->remPacketHandler(&myLoopPacketHandlerCB);
00169 myRobot->comStr(94, "");
00170 if (myFile != NULL)
00171 {
00172 fprintf(myFile, "# End of log\n");
00173 fclose(myFile);
00174 }
00175 }
00176
00177 AREXPORT bool ArSickLogger::loopPacketHandler(ArRobotPacket *packet)
00178 {
00179 unsigned char loops;
00180 if (packet->getID() != 0x96)
00181 return false;
00182 loops = packet->bufToUByte();
00183 unsigned char bit;
00184 int num;
00185 if (loops != myLastLoops)
00186 {
00187 for (bit = 1, num = 1; num <= 8; bit *= 2, num++)
00188 {
00189 if ((loops & bit) && !(myLastLoops & bit))
00190 {
00191 addTagToLog("loop: start %d", num);
00192 ArLog::log(ArLog::Normal, "Starting loop %d", num);
00193 }
00194 else if (!(loops & bit) && (myLastLoops & bit))
00195 {
00196 addTagToLog("loop: end %d", num);
00197 ArLog::log(ArLog::Normal, "Ending loop %d", num);
00198 }
00199 }
00200 }
00201 myLastLoops = loops;
00202 return true;
00203 }
00204
00213 AREXPORT void ArSickLogger::addTagToLogPlain(const char *str)
00214 {
00215 myTags.push_back(str);
00216 }
00217
00226 AREXPORT void ArSickLogger::addTagToLog(const char *str, ...)
00227 {
00228 char buf[2048];
00229 va_list ptr;
00230 va_start(ptr, str);
00231 vsprintf(buf, str, ptr);
00232 addTagToLogPlain(buf);
00233 va_end(ptr);
00234 }
00235
00236
00245 AREXPORT void ArSickLogger::addInfoToLogPlain(const char *str)
00246 {
00247 myInfos.push_back(str);
00248 }
00249
00257 AREXPORT void ArSickLogger::addInfoToLog(const char *str, ...)
00258 {
00259 char buf[2048];
00260 va_list ptr;
00261 va_start(ptr, str);
00262 vsprintf(buf, str, ptr);
00263 addInfoToLogPlain(buf);
00264 va_end(ptr);
00265 }
00266
00267 void ArSickLogger::goalKeyCallback(void)
00268 {
00269 myAddGoalKeyboard = true;
00270 }
00271
00272 void ArSickLogger::internalAddGoal(void)
00273 {
00274 bool joyButton;
00275 bool robotJoyButton;
00276
00277
00278
00279
00280 if (!myAddGoals && !myAddGoalExplicit)
00281 return;
00282
00283 if (myJoyHandler != NULL)
00284 joyButton = (myJoyHandler->getButton(2) ||
00285 myJoyHandler->getButton(3) ||
00286 myJoyHandler->getButton(4));
00287 else
00288 joyButton = (myRobot->getFlags() & ArUtil::BIT9);
00289
00290 if (myRobotJoyHandler != NULL)
00291 robotJoyButton = myRobotJoyHandler->getButton2();
00292 else
00293 robotJoyButton = false;
00294
00295
00296
00297
00298 if (myRobot->isConnected() &&
00299 (myAddGoalExplicit ||
00300 (myAddGoalKeyboard && !myLastAddGoalKeyboard) ||
00301 (joyButton && !myLastJoyButton) ||
00302 (robotJoyButton && !myLastRobotJoyButton)))
00303 {
00304 myFirstGoalTaken = true;
00305 myAddGoalExplicit = false;
00306 myLastGoalTakenTime.setToNow();
00307 myLastGoalTakenPose = myRobot->getEncoderPose();
00308
00309
00310 addTagToLog("cairn: GoalWithHeading \"\" ICON_GOALWITHHEADING \"goal%d\"", myNumGoal);
00311 ArLog::log(ArLog::Normal, "Goal %d taken", myNumGoal);
00312 myNumGoal++;
00313 }
00314 myLastAddGoalKeyboard = myAddGoalKeyboard;
00315 myLastJoyButton = joyButton;
00316 myLastRobotJoyButton = robotJoyButton;
00317
00318
00319
00320 myAddGoalKeyboard = false;
00321 }
00322
00323 void ArSickLogger::internalWriteTags(void)
00324 {
00325 time_t msec;
00326
00327
00328 while (myInfos.size() > 0)
00329 {
00330 if (myFile != NULL)
00331 {
00332 myWrote = true;
00333 fprintf(myFile, "%s\n", (*myInfos.begin()).c_str());
00334 }
00335 myInfos.pop_front();
00336 }
00337
00338
00339
00340 while (myTags.size() > 0)
00341 {
00342 if (myFile != NULL)
00343 {
00344 myWrote = true;
00345 msec = myStartTime.mSecSince();
00346 fprintf(myFile, "time: %ld.%ld\n", msec / 1000, msec % 1000);
00347 internalPrintPos(myRobot->getEncoderPose());
00348 fprintf(myFile, "%s\n", (*myTags.begin()).c_str());
00349 }
00350 myTags.pop_front();
00351 }
00352 }
00353
00354 void ArSickLogger::internalTakeReading(void)
00355 {
00356 const std::list<ArSensorReading *> *readings;
00357 std::list<ArSensorReading *>::const_iterator it;
00358 std::list<ArSensorReading *>::const_reverse_iterator rit;
00359 ArPose poseTaken;
00360 time_t msec;
00361 ArSensorReading *reading;
00362 bool usingAdjustedReadings;
00363
00364
00365
00366
00367
00368
00369
00370 if (myRobot->isConnected() && (!myFirstTaken || myTakeReadingExplicit ||
00371 myLast.findDistanceTo(myRobot->getEncoderPose()) > myDistDiff ||
00372 fabs(ArMath::subAngle(myLast.getTh(),
00373 myRobot->getEncoderPose().getTh())) > myDegDiff ||
00374 ((myLastVel < 0 && myRobot->getVel() > 0 ||
00375 myLastVel > 0 && myRobot->getVel() < 0) &&
00376 myLast.findDistanceTo(myRobot->getEncoderPose()) > 50)))
00377 {
00378 myWrote = true;
00379 mySick->lockDevice();
00382 if ((readings = mySick->getAdjustedRawReadings()) != NULL)
00383 {
00384 usingAdjustedReadings = true;
00385 }
00386 else
00387 {
00388 usingAdjustedReadings = false;
00389 readings = mySick->getRawReadings();
00390 }
00391 if (readings == NULL || (it = readings->begin()) == readings->end() ||
00392 myFile == NULL)
00393 {
00394 mySick->unlockDevice();
00395 return;
00396 }
00397 myTakeReadingExplicit = false;
00398 myScanNumber++;
00399 if (usingAdjustedReadings)
00400 ArLog::log(ArLog::Normal,
00401 "Taking adjusted readings from the %d laser values",
00402 readings->size());
00403 else
00404 ArLog::log(ArLog::Normal,
00405 "Taking readings from the %d laser values",
00406 readings->size());
00407 myFirstTaken = true;
00408 myLast = myRobot->getEncoderPose();
00409 poseTaken = (*readings->begin())->getEncoderPoseTaken();
00410 myLastVel = myRobot->getVel();
00411 msec = myStartTime.mSecSince();
00412 fprintf(myFile, "scan1Id: %d\n", myScanNumber);
00413 fprintf(myFile, "time: %ld.%ld\n", msec / 1000, msec % 1000);
00414
00415
00416
00417 internalPrintPos(poseTaken);
00418
00419 if (myUseReflectorValues)
00420 {
00421 fprintf(myFile, "reflector1: ");
00422
00423 if (!mySick->isLaserFlipped())
00424 {
00425
00426 for (it = readings->begin(); it != readings->end(); it++)
00427 {
00428 reading = (*it);
00429 if (!reading->getIgnoreThisReading())
00430 fprintf(myFile, "%d ", reading->getExtraInt());
00431 else
00432 fprintf(myFile, "0 ");
00433 }
00434 }
00435 else
00436 {
00437 for (rit = readings->rbegin(); rit != readings->rend(); rit++)
00438 {
00439 reading = (*rit);
00440 if (!reading->getIgnoreThisReading())
00441 fprintf(myFile, "%d ", reading->getExtraInt());
00442 else
00443 fprintf(myFile, "0 ");
00444 }
00445 }
00446 fprintf(myFile, "\n");
00447 }
00453 if (myOldReadings)
00454 {
00455 fprintf(myFile, "sick1: ");
00456
00457 if (!mySick->isLaserFlipped())
00458 {
00459
00460 for (it = readings->begin(); it != readings->end(); it++)
00461 {
00462 reading = (*it);
00463 fprintf(myFile, "%d ", reading->getRange());
00464 }
00465 }
00466 else
00467 {
00468 for (rit = readings->rbegin(); rit != readings->rend(); rit++)
00469 {
00470 reading = (*rit);
00471 fprintf(myFile, "%d ", reading->getRange());
00472 }
00473 }
00474 fprintf(myFile, "\n");
00475 }
00476 if (myNewReadings)
00477 {
00478 fprintf(myFile, "scan1: ");
00479
00480 if (!mySick->isLaserFlipped())
00481 {
00482
00483 for (it = readings->begin(); it != readings->end(); it++)
00484 {
00485 reading = (*it);
00486 if (!reading->getIgnoreThisReading())
00487 fprintf(myFile, "%.0f %.0f ",
00488 reading->getLocalX() - mySick->getSensorPositionX(),
00489 reading->getLocalY() - mySick->getSensorPositionY());
00490 else
00491 fprintf(myFile, "0 0 ");
00492 }
00493 }
00494 else
00495 {
00496 for (rit = readings->rbegin(); rit != readings->rend(); rit++)
00497 {
00498 reading = (*rit);
00499 if (!reading->getIgnoreThisReading())
00500 fprintf(myFile, "%.0f %.0f ",
00501 reading->getLocalX() - mySick->getSensorPositionX(),
00502 reading->getLocalY() - mySick->getSensorPositionY());
00503 else
00504 fprintf(myFile, "0 0 ");
00505 }
00506 }
00507 fprintf(myFile, "\n");
00508 }
00509 mySick->unlockDevice();
00510 }
00511 }
00512
00513 void ArSickLogger::internalPrintPos(ArPose poseTaken)
00514 {
00515 if (myFile == NULL)
00516 return;
00517 ArPose encoderPose = myRobot->getEncoderPose();
00518 ArPose rawEncoderPose = myRobot->getRawEncoderPose();
00519 ArTransform normalToRaw(rawEncoderPose, encoderPose);
00520
00521 ArPose rawPose;
00522 rawPose = normalToRaw.doInvTransform(poseTaken);
00523 fprintf(myFile, "#rawRobot: %.0f %.0f %.2f %.0f %.0f\n",
00524 rawPose.getX(),
00525 rawPose.getY(),
00526 rawPose.getTh(),
00527 myRobot->getVel(),
00528 myRobot->getRotVel());
00529 fprintf(myFile, "robot: %.0f %.0f %.2f %.0f %.0f\n",
00530 poseTaken.getX(),
00531 poseTaken.getY(),
00532 poseTaken.getTh(),
00533 myRobot->getVel(),
00534 myRobot->getRotVel());
00535 }
00536
00537 AREXPORT void ArSickLogger::robotTask(void)
00538 {
00539
00540
00541 internalAddGoal();
00542
00543
00544 internalWriteTags();
00545
00546
00547 internalTakeReading();
00548
00549
00550 if (myWrote)
00551 {
00552 fflush(myFile);
00553 #ifndef WIN32
00554 fsync(fileno(myFile));
00555 #endif
00556 }
00557 myWrote = false;
00558 }
00559
00560
00561
00562