00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "LogPlayer.h"
00010 #include "Representations/Perception/Image.h"
00011 #include "Representations/Perception/JPEGImage.h"
00012 #include "Representations/Perception/CameraMatrix.h"
00013 #include "Representations/Perception/SpecialPercept.h"
00014 #include "Representations/Cognition/RobotPose.h"
00015 #include "Representations/Cognition/BallModel.h"
00016 #include "Representations/Cognition/PlayerPoseCollection.h"
00017 #include "Representations/Cognition/ObstaclesModel.h"
00018 #include "Representations/Cognition/RobotState.h"
00019 #include "Platform/SystemCall.h"
00020
00021 LogPlayer::LogPlayer(MessageQueue& targetQueue)
00022 : targetQueue(targetQueue),
00023 smoothingEnabled(false),
00024 playSpeed(1)
00025 {
00026 _new();
00027 }
00028
00029 void LogPlayer::_new()
00030 {
00031 clear();
00032 stop();
00033 state = initial;
00034 }
00035
00036 bool LogPlayer::open(const char* fileName)
00037 {
00038 InBinaryFile file(fileName);
00039 if (file.exists())
00040 {
00041 clear();
00042 file >> *this;
00043 stop();
00044 return true;
00045 }
00046 return false;
00047 }
00048
00049 void LogPlayer::play()
00050 {
00051 pause();
00052 state = playing;
00053 }
00054
00055 void LogPlayer::stop()
00056 {
00057 pause();
00058 currentMessageNumber = -1;
00059 }
00060
00061 void LogPlayer::pause()
00062 {
00063 if (getNumberOfMessages() == 0) state = initial;
00064 else state = paused;
00065
00066 timeOfFirstPlayedMessage = 0;
00067 timeWhenFirstMessageWasPlayed = 0;
00068 }
00069
00070 void LogPlayer::stepBackward()
00071 {
00072 pause();
00073
00074 if (state == paused && currentMessageNumber > 0 )
00075 copyMessage(--currentMessageNumber,targetQueue);
00076 }
00077
00078 void LogPlayer::stepForward()
00079 {
00080 pause();
00081
00082 if ((state == paused) && (currentMessageNumber < getNumberOfMessages()-1))
00083 copyMessage(++currentMessageNumber,targetQueue);
00084 }
00085
00086 void LogPlayer::stepRepeat()
00087 {
00088 pause();
00089
00090 if (state == paused && currentMessageNumber >= 0 )
00091 copyMessage(currentMessageNumber,targetQueue);
00092 }
00093
00094 void LogPlayer::jumpFrame(int frame)
00095 {
00096 pause();
00097
00098 if (state == paused && frame >= 1 && frame <= getNumberOfMessages() )
00099 copyMessage(currentMessageNumber = frame - 1,targetQueue);
00100 }
00101
00102 bool LogPlayer::save(const char* fileName)
00103 {
00104 if (getNumberOfMessages() == 0) return false;
00105
00106 OutBinaryFile file(fileName);
00107 if (file.exists())
00108 {
00109 file << *this;
00110 return true;
00111 }
00112 return false;
00113 }
00114
00115
00116 void LogPlayer::convertIntString(char* str, int value)
00117 {
00118 char temp[256];
00119 int i=0;
00120 while(value > 0)
00121 {
00122 temp[i] = (char)(value % 10) + 48;
00123 value = value / 10; i++;
00124 }
00125 for (int j=i-1; j>=0; j--)
00126 str[j] = temp[i-j-1];
00127 str[i] = '\0';
00128 }
00129
00130 bool LogPlayer::saveAMV(const char* fileName)
00131 {
00132 if (getNumberOfMessages() == 0) return false;
00133 OutBinaryFile file(fileName);
00134 if (file.exists())
00135 {
00136 unsigned char* imgBuffer;
00137 CameraMatrix cameraMatrix;
00138 Image image;
00139 bool headerGenerated = false;
00140 for (currentMessageNumber=0; currentMessageNumber<getNumberOfMessages();currentMessageNumber++)
00141 {
00142 queue.setSelectedMessageForReading(currentMessageNumber);
00143 if (getCurrentMessageID()==idImage)
00144 {
00145 in.bin >> image >> cameraMatrix;
00146 }
00147 else if (getCurrentMessageID()==idJPEGImage)
00148 {
00149 JPEGImage jpegImage;
00150 in.bin >> jpegImage >> cameraMatrix;
00151 jpegImage.toImage(image);
00152 }
00153 else
00154 continue;
00155 if (!headerGenerated){
00156 char* magicNumber = "AIBOMOVIE";
00157 unsigned char padding = 0;
00158 unsigned char magicNumberLenUTF = 9;
00159 file << padding << magicNumberLenUTF;
00160 for (int k=0; k<magicNumberLenUTF; k++)
00161 file << magicNumber[k];
00162 char widthStr[10];
00163 char heightStr[10];
00164 unsigned char widthLenUTF = 3;
00165 unsigned char heightLenUTF = 3;
00166 convertIntString(widthStr, image.cameraInfo.resolutionWidth);
00167 convertIntString(heightStr, image.cameraInfo.resolutionHeight);
00168 file << padding << widthLenUTF;
00169 for (k=0; k<widthLenUTF; k++)
00170 file << widthStr[k];
00171 file << padding << heightLenUTF;
00172 for (k=0; k<heightLenUTF; k++)
00173 file << heightStr[k];
00174 char movType = '0';
00175 unsigned char movTypeLenUTF = 1;
00176 file << padding << movTypeLenUTF << movType;
00177 imgBuffer = new unsigned char[3*image.cameraInfo.resolutionWidth*image.cameraInfo.resolutionHeight];
00178 headerGenerated = true;
00179 }
00180 int lineWidth = image.cameraInfo.resolutionWidth;
00181 for (int h=0; h<image.cameraInfo.resolutionHeight; h++)
00182 for (int w=0; w<image.cameraInfo.resolutionWidth; w++)
00183 {
00184 imgBuffer[3*(h*lineWidth + w) + 0] = image.image[h][0][w];
00185 imgBuffer[3*(h*lineWidth + w) + 2] = image.image[h][1][w];
00186 imgBuffer[3*(h*lineWidth + w) + 1] = image.image[h][2][w];
00187 }
00188 file.write(imgBuffer,3*image.cameraInfo.resolutionWidth*image.cameraInfo.resolutionHeight);
00189 }
00190 delete [] imgBuffer;
00191 stop();
00192 return true;
00193 }
00194 stop();
00195 return false;
00196 }
00197
00198 void LogPlayer::saveCSVrow(OutTextRawFile& file, double* row, unsigned int rowLen)
00199 {
00200 if (fabs(row[0])<=1e10)
00201 {
00202 file << row[0];
00203 for (unsigned int i=1;i<rowLen;i++)
00204 {
00205 if (fabs(row[i])>1e10)
00206 {
00207 file << ", -";
00208 }
00209 else
00210 {
00211 file << ", " << row[i];
00212 }
00213 row[i]=1e11;
00214 }
00215 file << "\n";
00216 }
00217 }
00218
00219 bool LogPlayer::saveCSV(const char* fileName)
00220 {
00221
00222 static const unsigned int rowLen=7;
00223 if (getNumberOfMessages() == 0) return false;
00224 OutTextRawFile file(fileName);
00225 if (file.exists())
00226 {
00227 double row[rowLen];
00228 for (int i=1;i<rowLen;i++)
00229 {
00230 row[i]=1e11;
00231 }
00232 file << "frame, specialPercept.checkerPose.x, specialPercept.checkerPose.y, specialPercept.checkerPose.r, robotPose.x, robotPose.y, robotPose.r\n";
00233 for (currentMessageNumber=0; currentMessageNumber<getNumberOfMessages();currentMessageNumber++)
00234 {
00235 queue.setSelectedMessageForReading(currentMessageNumber);
00236 switch (getCurrentMessageID())
00237 {
00238 case idSpecialPercept:
00239 {
00240 Player pl;
00241 CameraMatrix cm;
00242 SpecialPercept specialPercept;
00243 in.bin >> pl >> specialPercept >> cm;
00244 if (specialPercept.type==SpecialPercept::checkerboard)
00245 {
00246 if (specialPercept.frameNumber!=row[0])
00247 {
00248 saveCSVrow(file, row, rowLen);
00249 row[0]=specialPercept.frameNumber;
00250 }
00251 row[1]=specialPercept.checkerPose.translation.x;
00252 row[2]=specialPercept.checkerPose.translation.y;
00253 row[3]=specialPercept.checkerPose.rotation;
00254 }
00255 }
00256 break;
00257 case idWorldState:
00258 {
00259 RobotPose robotPose;
00260 BallModel ballModel;
00261 PlayerPoseCollection playerPoseCollection;
00262 ObstaclesModel obstaclesModel;
00263 RobotState robotState;
00264 CameraMatrix cameraMatrix;
00265 CameraInfo cameraInfo;
00266 in.bin >> RECEIVE_WORLDSTATE(robotPose,ballModel,playerPoseCollection,
00267 obstaclesModel,robotState,cameraMatrix,cameraInfo);
00268 if (robotPose.frameNumber!=row[0])
00269 {
00270 saveCSVrow(file, row, rowLen);
00271 row[0]=robotPose.frameNumber;
00272 }
00273 row[4]=robotPose.translation.x;
00274 row[5]=robotPose.translation.y;
00275 row[6]=robotPose.rotation;
00276 }
00277 break;
00278 default:
00279 continue;
00280 }
00281 }
00282 saveCSVrow(file, row, rowLen);
00283 stop();
00284 return true;
00285 }
00286 stop();
00287 return false;
00288 }
00289
00290 bool LogPlayer::saveImages(const char* fileName)
00291 {
00292 struct BmpHeader{
00293 unsigned long k0,k1,k2;
00294 unsigned long ofs1,ofs2;
00295 unsigned long xsiz,ysiz;
00296 unsigned long modbit;
00297 unsigned long z1;
00298 unsigned long len;
00299 unsigned long z2,z3,z4,z5;
00300 } bmpHeader;
00301
00302 char name[512];
00303 char fname[512];
00304 strcpy(name,fileName);
00305 if ((strlen(name)>4)&&((strncmp(name+strlen(name)-4,".bmp",4)==0)||(strncmp(name+strlen(name)-4,".jpg",4)==0)))
00306 {
00307 *(name+strlen(name)-4) = 0;
00308 }
00309 if ((strlen(name)>4)&&((strncmp(name+strlen(name)-4,"_000",4)==0)||(strncmp(name+strlen(name)-4,"_001",4)==0)))
00310 {
00311 *(name+strlen(name)-4) = 0;
00312 }
00313 int i=0;
00314 for (currentMessageNumber=0; currentMessageNumber<getNumberOfMessages();currentMessageNumber++)
00315 {
00316 CameraMatrix cameraMatrix;
00317 queue.setSelectedMessageForReading(currentMessageNumber);
00318 Image image;
00319 if (getCurrentMessageID()==idImage)
00320 {
00321 in.bin >> image >> cameraMatrix;
00322 }
00323 else if (getCurrentMessageID()==idJPEGImage)
00324 {
00325 JPEGImage jpegImage;
00326 in.bin >> jpegImage >> cameraMatrix;
00327 jpegImage.toImage(image);
00328 }
00329 else
00330 continue;
00331
00332 Image rgbImage;
00333 rgbImage.convertFromYUVToRGB(image);
00334
00335 sprintf(fname,"%s_%03i.bmp",name,i++);
00336 OutBinaryFile file(fname);
00337 if (file.exists())
00338 {
00339 long truelinelength=(3*rgbImage.cameraInfo.resolutionWidth+3) & 0xfffffc;
00340 char line[3*208+4];
00341 memset(line,0,truelinelength);
00342 bmpHeader.k0=0x4d420000;
00343 bmpHeader.k1=rgbImage.cameraInfo.resolutionHeight*truelinelength+0x36;
00344 bmpHeader.k2=0;
00345 bmpHeader.ofs1=0x36;
00346 bmpHeader.ofs2=0x28;
00347 bmpHeader.xsiz=rgbImage.cameraInfo.resolutionWidth;
00348 bmpHeader.ysiz=rgbImage.cameraInfo.resolutionHeight;
00349 bmpHeader.modbit=0x00180001;
00350 bmpHeader.z1=0;
00351 bmpHeader.len=truelinelength*rgbImage.cameraInfo.resolutionHeight;
00352 bmpHeader.z2=0;
00353 bmpHeader.z3=0;
00354 bmpHeader.z4=0;
00355 bmpHeader.z5=0;
00356 file.write(2+(char*)&bmpHeader,sizeof(bmpHeader)-2);
00357 for (int i=rgbImage.cameraInfo.resolutionHeight-1; i>=0; i--)
00358 {
00359 int ofs=0;
00360 for (int j=0;j<rgbImage.cameraInfo.resolutionWidth;j++)
00361 {
00362 line[ofs++]=rgbImage.image[i][2][j];
00363 line[ofs++]=rgbImage.image[i][1][j];
00364 line[ofs++]=rgbImage.image[i][0][j];
00365 }
00366 file.write(line,truelinelength);
00367 }
00368 }
00369 else
00370 {
00371 stop();
00372 return false;
00373 }
00374 }
00375 stop();
00376 return true;
00377 }
00378
00379 void LogPlayer::record()
00380 {
00381 switch(state)
00382 {
00383 case recording:
00384 pause();
00385 break;
00386 case paused:
00387 case initial:
00388 case playing:
00389 state = recording;
00390 break;
00391 }
00392 }
00393
00394 void LogPlayer::smooth()
00395 {
00396 if(smoothingEnabled)
00397 smoothingEnabled = false;
00398 else
00399 smoothingEnabled = true;
00400 }
00401
00402 void LogPlayer::setPlaySpeed(double speed)
00403 {
00404 playSpeed = speed;
00405 timeWhenFirstMessageWasPlayed = 0;
00406 }
00407
00408 void LogPlayer::handleMessage(InMessage& message)
00409 {
00410 if (state == recording)
00411 message >> *this;
00412 }
00413
00414 LogPlayer::LogPlayerState LogPlayer::getState()
00415 {
00416 return state;
00417 }
00418
00419 void LogPlayer::onIdle()
00420 {
00421 if (state == playing)
00422 {
00423 while (1)
00424 {
00425 if (currentMessageNumber < getNumberOfMessages()-1)
00426 {
00427 if (timeWhenFirstMessageWasPlayed == 0 ||
00428 (double)(int(getTimeStamp(currentMessageNumber+1)) - int(timeOfFirstPlayedMessage))
00429 > (double)(SystemCall::getTimeSince(timeWhenFirstMessageWasPlayed)) * playSpeed + 4000)
00430 {
00431 copyMessage(++currentMessageNumber,targetQueue);
00432 timeOfFirstPlayedMessage = getTimeStamp(currentMessageNumber);
00433 timeWhenFirstMessageWasPlayed = SystemCall::getCurrentSystemTime();
00434 }
00435 else
00436 {
00437 if ((double)(int(getTimeStamp(currentMessageNumber+1)) - int(timeOfFirstPlayedMessage))
00438 < (double)(SystemCall::getTimeSince(timeWhenFirstMessageWasPlayed)) * playSpeed)
00439 {
00440 copyMessage(++currentMessageNumber,targetQueue);
00441 }
00442 else
00443 {
00444 break;
00445 }
00446 }
00447 }
00448 else
00449 {
00450 stop();
00451 break;
00452 }
00453 }
00454 }
00455 }
00456
00457 unsigned long LogPlayer::getTimeStamp(int message)
00458 {
00459 return queue.getTimeStamp(message);
00460 }
00461
00462 int LogPlayer::getNumberOfMessages() const
00463 {
00464 return queue.getNumberOfMessages();
00465 }
00466
00467 int LogPlayer::getCurrentMessageNumber() const
00468 {
00469 return currentMessageNumber;
00470 }
00471
00472 MessageID LogPlayer::getCurrentMessageID() const
00473 {
00474 if(currentMessageNumber <= 0) return undefined;
00475 return queue.getMessageID();
00476 }
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553