00001 #include "Raster/Raster.H"
00002 #include "Robots/Beobot2/Hardware/BeoPilot.H"
00003 #include "Ice/BeobotEvents.ice.H"
00004 #include "Component/ModelParam.H"
00005 #include "Component/ModelOptionDef.H"
00006 #include "Util/sformat.H"
00007 #include "Util/MathFunctions.H"
00008 #include "Image/ShapeOps.H"
00009 #include <iostream>
00010 #include <stdio.h>
00011 #include <sys/types.h>
00012 #include <sys/stat.h>
00013 #include <dirent.h>
00014 #include <unistd.h>
00015 #define LOG_FOLDER "../data/logs/IROS10_Equad"
00016 const ModelOptionCateg MOC_BeoPilot = {
00017 MOC_SORTPRI_3, "Beobot Pilot Related Options" };
00018
00019 const ModelOptionDef OPT_MinimumSafeDistance =
00020 { MODOPT_ARG(float), "MinimumSafeDistance", &MOC_BeoPilot, OPTEXP_CORE,
00021 "The minimum distance (in meters) to objects we can allow before cutting off the motors.",
00022 "min-distance", '\0', "float", ".5"};
00023
00024 const ModelOptionDef OPT_MaxSpeed =
00025 { MODOPT_ARG(float), "MaxSpeed", &MOC_BeoPilot, OPTEXP_CORE,
00026 "The maximum speed of the robot (from [0 .. 1]).",
00027 "max-speed", '\0', "float", "1.0"};
00028
00029 const ModelOptionDef OPT_IgnoreSonar =
00030 { MODOPT_ARG(bool), "IgnoreSonar", &MOC_BeoPilot, OPTEXP_CORE,
00031 "Do we want to ignore the sonar for proximity warnings. Use this with caution, as someone could get hurt!?",
00032 "ignore-sonar", '\0', "true | false", "true"};
00033
00034 const ModelOptionDef OPT_LogFile =
00035 { MODOPT_ARG(std::string), "LogFile", &MOC_BeoPilot, OPTEXP_CORE,
00036 "There are 3 mode for input log file name \n"
00037 "you can enter\n"
00038 "1) ./bin/app-BeoPilot --log-file=<Full Log File Path>\n"
00039 " it will open the file directly\n"
00040 "2) ./bin/app-BeoPilot --log-file=<date>\n"
00041 " it will look for ../data/logs/<date>/Log_<date>.txt\n"
00042 " The date formate can be flexible.\n"
00043 " You can enter full date such as 2009_11_03__14_03_49\n"
00044 " or 20091103 or 091103 or 1403 or 140349. \n"
00045 " If there are more than one match, \n"
00046 " it will list all options for choosen.\n"
00047 "3) ./bin/app-BeoPilot --log-file=search\n"
00048 " it will look for all directory under ../data/logs/\n"
00049 " and list all files for choosen\n",
00050 "log-file", '\0', "<string>", "NULL"};
00051
00052
00053 const ModelOptionDef OPT_ReplaySpeed=
00054 { MODOPT_ARG(int), "ReplaySpeed", &MOC_BeoPilot, OPTEXP_CORE,
00055 "The replay speed from the Log file,default is 1x. To speed up the speed, using --speed=2 or faster",
00056 "speed", '\0', "int", "1"};
00057
00058 BeoPilot::BeoPilot(int id, OptionManager& mgr,
00059 const std::string& descrName, const std::string& tagName) :
00060 RobotBrainComponent(mgr, descrName, tagName),
00061 itsSerial(new Serial(mgr)),
00062 itsSerialTimer(1000000),
00063 itsCurrMessageID(0),
00064 itsCurrentTimeIndex(0),
00065 itsLogTimer(1000000),
00066 itsLoadFromLogFile(false),
00067 itsLogLeftMotorVelocity(0.0),
00068 itsLogRightMotorVelocity(0.0),
00069 itsLogPosition(0.0,0.0,0.0),
00070 itsLogDiffPosition(0.0,0.0,0.0),
00071 itsRCChannels(7, -1),
00072 itsEmergencyMode(-1),
00073 itsPosition(0.0,0.0,0.0),
00074 itsDiffPosition(0.0,0.0,0.0),
00075 itsMapImage(800-320,344,ZEROS),
00076 itsEncoderTimer(1000000),
00077 itsLeftMotorVelocity(0.0),
00078 itsRightMotorVelocity(0.0),
00079 itsPidLeft(0.3,0.000,0.00,0.0,0.0,0,0,0,1.0,-1.0),
00080 itsPidRight(0.0,0.000,0.00,0.0,0.0,0,0,0,1.0,-1.0),
00081 itsSonarTimeout(.5),
00082 itsControlImage(512,256,ZEROS),
00083 itsDispImage(800,600,ZEROS),
00084 itsDispCameraImage(320,240,ZEROS),
00085 itsMeterXwin(itsDispImage,"Pilot Control"),
00086
00087 itsDisplayUpdateRate(.05),
00088 itsMapScale(100.0),
00089 itsChannelMeters(7, SimpleMeter(20, 60, 1040,1921)),
00090 itsVelocityQue(50),
00091 itsVelocityTargetQue(50),
00092 itsMinimumSafeDistance(&OPT_MinimumSafeDistance, this, 0),
00093 itsMaxSpeed(&OPT_MaxSpeed, this, 0),
00094 itsIgnoreSonar(&OPT_IgnoreSonar, this, 0),
00095 itsLogFile(&OPT_LogFile, this, 0),
00096 itsReplaySpeed(&OPT_ReplaySpeed, this, 0)
00097 {
00098 addSubComponent(itsSerial);
00099
00100 itsSerial->configureSearch ("motorboard", 115200);
00101 }
00102
00103 void BeoPilot::checkLogFile()
00104 {
00105 if(itsLogFile.getVal() =="NULL"){
00106 LINFO("Start BeoPilot with real device");
00107 }else if(itsLogFile.getVal() =="search"){
00108 LINFO("Search for all log file");
00109 DIR *dir_p;
00110 struct dirent *entry_p;
00111 dir_p = ::opendir(LOG_FOLDER);
00112 if(dir_p == NULL)
00113 LFATAL("Can Not Open ../data/logs directory");
00114
00115
00116 std::vector<std::string> subdir;
00117 while((entry_p = ::readdir(dir_p)))
00118 {
00119 std::string subdirname(entry_p->d_name);
00120 if(subdirname != "." && subdirname !="..")
00121 {
00122
00123 subdir.push_back(subdirname);
00124 }
00125 }
00126 (void)::closedir(dir_p);
00127
00128
00129 std::sort(subdir.begin(),subdir.end());
00130 for(int i = 0;i < (int)subdir.size();i++)
00131 {
00132 LINFO("File[%d]:[%s]",i+1,subdir[i].c_str());
00133 }
00134
00135 int option;
00136 do{
00137 LINFO("Please Choose a File Number:");
00138 scanf("%d",&option);
00139 if(option <1 ||option >int(subdir.size()))
00140 LINFO("Option Invalid, please try again");
00141 }while(option < 1 || option > int(subdir.size()));
00142 LINFO("Your Choose is [%d] filename[%s] ",option,subdir[option-1].c_str());
00143
00144
00145
00146 std::string logFileName(
00147 sformat("%s/%s/%s.txt",
00148 LOG_FOLDER,
00149 subdir[option-1].c_str(),
00150 subdir[option-1].c_str()
00151
00152 ));
00153 itsLogFile.setVal(logFileName);
00154 loadFromLogFile();
00155 }else{
00156 LINFO("LogFileName:[%s]",itsLogFile.getVal().c_str());
00157 loadFromLogFile();
00158 }
00159
00160
00161 }
00162
00163 void BeoPilot::loadFromLogFile()
00164 {
00165
00166
00167 FILE *logFile = fopen(itsLogFile.getVal().c_str(),"r");
00168 if(logFile == NULL)
00169 {
00170 LFATAL("can't not open file: %s",itsLogFile.getVal().c_str());
00171 }else
00172 {
00173 char line[512];
00174 while(fgets(line,sizeof line,logFile)!= NULL)
00175 {
00176 float time,transVel,rotVel,encoderX,encoderY,encoderOri,rcTransVel,rcRotVel;
00177 int rcMode;
00178 int ret = sscanf (line,"[%f] MTR rcMode: %d, transVel: %f rotVel: %f encoderX: %f encoderY: %f encoderOri: %f rcTransVel: %f rcRotVel: %f",
00179 &time, &rcMode, &transVel, &rotVel, &encoderX, &encoderY, &encoderOri, &rcTransVel, &rcRotVel);
00180 if(ret == 9){
00181 motorData tmp;
00182 tmp.time = time;
00183 tmp.rcMode = rcMode;
00184 tmp.transVel = transVel;
00185 tmp.rotVel = rotVel;
00186 tmp.encoderX = encoderX;
00187 tmp.encoderY = encoderY;
00188 tmp.encoderOri = encoderOri;
00189 tmp.rcTransVel = rcTransVel;
00190 tmp.rcRotVel = rcRotVel;
00191 itsLogData.push_back(tmp);
00192 LINFO("Got Motor Data %f %d",time,rcMode);
00193
00194 }
00195
00196 std::string imagePath;
00197 char imgPath[256];
00198 ret = sscanf(line,"[%f] CAM filename: %s", &time, imgPath);
00199 if(ret == 2)
00200 {
00201 imageData imgData;
00202 imgData.time = time;
00203 imgData.imagePath = imgPath;
00204 itsLogImageData.push_back(imgData);
00205 LINFO("Got Image at %f path=%s",time,imgPath);
00206 }
00207
00208 }
00209 LINFO("Load Log file with %d motor command lines",(int)itsLogData.size());
00210 LINFO("Load Log file with %d Images",(int)itsLogImageData.size());
00211 itsLoadFromLogFile = true;
00212 itsLogTimer.reset();
00213
00214 }
00215
00216
00217
00218 }
00219
00220
00221 void BeoPilot::start3()
00222 {
00223 checkLogFile();
00224
00225
00226
00227
00228 if(itsSerial->isSerialOk())
00229 LINFO("%s found on %s", itsSerial->getDeviceDescriptor().c_str(), itsSerial->getDevName().c_str());
00230 resetEncoder();
00231
00232 if(itsMinimumSafeDistance.getVal() < 0)
00233 LFATAL("Invalid Minimum Safe Distance (%f). Must be > 0!", itsMinimumSafeDistance.getVal());
00234 if(itsMaxSpeed.getVal() > 1.0 || itsMaxSpeed.getVal() < 0)
00235 LFATAL("Invalid Maximum Speed Distance (%f). Must be > 0 && < 1.0!", itsMaxSpeed.getVal());
00236 }
00237
00238
00239 BeoPilot::~BeoPilot()
00240 {
00241
00242 SetMotors(0,0);
00243 }
00244
00245
00246 void BeoPilot::registerTopics()
00247 {
00248 registerSubscription("MotorRequestTopic");
00249 registerSubscription("SonarMessageTopic");
00250 registerPublisher("MotorMessageTopic");
00251 }
00252
00253
00254 void BeoPilot::evolve()
00255 {
00256
00257
00258 UpdateRCStatus();
00259 itsVelocityTargetQue.add(itsRcTransSpeedCapped);
00260
00261
00262
00263
00264 if(itsLoadFromLogFile){
00265
00266
00267
00268
00269
00270
00271
00272 if(itsEmergencyMode == -1||itsEmergencyMode == 255)
00273 {
00274 itsLogTimer.resume();
00275 getCurrentLogData();
00276 }
00277 else if(itsEmergencyMode == 0 && itsRemoteMode == 3)
00278 {
00279 itsLogTimer.resume();
00280 getCurrentLogData();
00281 SetMotors(itsRotationalSpeed,itsForwardSpeed);
00282 }
00283 else{
00284 itsLogTimer.pause();
00285 LINFO("Wait for RC mode 3");
00286 }
00287 uint64 time = itsLogTimer.get()/1000.0;
00288 LDEBUG("Current Log Timer is %f",(double)time);
00289 }
00290 else{
00291
00292
00293 float loc_rotVel;
00294 float loc_transVel;
00295 bool loc_sonarProxAlert;
00296
00297
00298
00299
00300 itsSonarMutex.lock();
00301 {
00302 if(itsSonarReadings.size() > 0)
00303 {
00304 float minSonarReading = *(std::min_element(itsSonarReadings.begin(), itsSonarReadings.end()));
00305 if(itsSonarTimer.getSecs() > itsSonarTimeout || minSonarReading < itsMinimumSafeDistance.getVal())
00306 itsSonarProxAlert = true;
00307 else
00308 itsSonarProxAlert = false;
00309 }
00310 else
00311 itsSonarProxAlert = true;
00312
00313 loc_sonarProxAlert = itsSonarProxAlert;
00314 }
00315 itsSonarMutex.unlock();
00316
00317
00318
00319 itsSpeedMutex.lock();
00320 {
00321 itsRotationalSpeed = itsRotationalSpeedReq;
00322 itsForwardSpeed = itsForwardSpeedReq;
00323
00324
00325 if((itsIgnoreSonar.getVal() == false) && loc_sonarProxAlert)
00326 {
00327 LINFO("SONAR ERROR!");
00328 itsRotationalSpeed = 0;
00329 itsForwardSpeed = 0;
00330 }
00331
00332
00333
00334 if(itsRotationalSpeed > itsMaxSpeed.getVal())
00335 itsRotationalSpeed = itsMaxSpeed.getVal();
00336 else if(itsRotationalSpeed < -itsMaxSpeed.getVal())
00337 itsRotationalSpeed = -itsMaxSpeed.getVal();
00338
00339 if(itsForwardSpeed > itsMaxSpeed.getVal())
00340 itsForwardSpeed = itsMaxSpeed.getVal();
00341 else if(itsForwardSpeed < -itsMaxSpeed.getVal())
00342 itsForwardSpeed = -itsMaxSpeed.getVal();
00343
00344
00345 loc_rotVel = itsRotationalSpeed;
00346 loc_transVel = itsForwardSpeed;
00347
00348 }
00349 itsSpeedMutex.unlock();
00350
00351 if(itsRemoteMode == 1 ||itsRemoteMode == 3)
00352 {
00353
00354 SetMotors(loc_rotVel, loc_transVel);
00355 }else if(itsRemoteMode == 2)
00356 {
00357 double m1velReq = (itsRcTransSpeedCapped + itsRcRotSpeedCapped)*3.0;
00358 double m2velReq = (itsRcTransSpeedCapped - itsRcRotSpeedCapped)*3.0;
00359
00360 float leftPWM = itsPidLeft.update(m1velReq,itsLeftMotorVelocity);
00361 float rightPWM = itsPidRight.update(itsRightMotorVelocity,m2velReq);
00362
00363 double transPWM = leftPWM;
00364 double rotPWM = 0.0;
00365
00366 LINFO("LEFT PWM %f, RIGT PWM %f",leftPWM,rightPWM);
00367 LINFO("LEFT Request %f, LEFT Cur %f",m1velReq,itsLeftMotorVelocity);
00368 LINFO("RIGT Request %f, RIGT Cur %f",m2velReq,itsRightMotorVelocity);
00369 LINFO("Rc Tran %f Rc Rot %f",itsRcTransSpeedCapped,itsRcRotSpeedCapped);
00370 LINFO("Pwm Tran %f Pwm Rot %f",transPWM,rotPWM);
00371 LINFO("=====================================================");
00372 SetMotors(rotPWM,transPWM) ;
00373 }
00374
00375
00376 BeobotEvents::MotorMessagePtr msg = new BeobotEvents::MotorMessage;
00377
00378 msg->RequestID = itsCurrMessageID;
00379
00380 msg->transVel = loc_transVel;
00381 msg->rotVel = loc_rotVel;
00382 msg->motor1 = Ice::Int(itsMotor1Speed);
00383 msg->motor2 = Ice::Int(itsMotor2Speed);
00384
00385 msg->encoderX = itsDiffPosition.x;
00386 msg->encoderY = itsDiffPosition.y;
00387 msg->encoderOri = itsDiffPosition.z;
00388
00389 msg->rcTransVel = itsRcTransSpeed;
00390 msg->rcRotVel = itsRcRotSpeed;
00391 msg->rcMode = itsRemoteMode;
00392
00393 this->publish("MotorMessageTopic", msg);
00394
00395
00396
00397 itsCurrMessageID++;
00398 usleep(10000);
00399 }
00400
00401 updateGUI();
00402
00403
00404 double locSerialTime = (double) itsSerialTimer.get()/1000000.0;
00405 int code = itsSerial->getSerialErrno();
00406 if(code==0||code==15){
00407 itsSerialTimer.reset();
00408 }else if(locSerialTime > 3.0){
00409 LINFO("Try reconnect Timer:%f",locSerialTime);
00410 itsSerialTimer.reset();
00411 itsSerial->enablePort(itsSerial->getDevName().c_str());
00412 LINFO("Tried Reconnect");
00413 usleep(100000);
00414 }else{
00415 LINFO("Serial Timer:%f",locSerialTime);
00416 LINFO("Serial Error Number:[%d]",itsSerial->getSerialErrno());
00417 }
00418 }
00419
00420 void BeoPilot::UpdateRCStatus()
00421 {
00422 unsigned char cmd = 107;
00423 itsSerial->write(cmd);
00424 std::vector<unsigned char> frame = itsSerial->readFrame(cmd, 255, -1, .2);
00425
00426
00427 if(frame.size() == 26)
00428 {
00429 itsRCChannels[0] = ((0x0FF & frame[ 0]) << 8) |
00430 ((0x0FF & frame[ 1]) << 0);
00431
00432 itsRCChannels[1] = ((0x0FF & frame[ 2]) << 8) |
00433 ((0x0FF & frame[ 3]) << 0);
00434
00435 itsRCChannels[2] = ((0x0FF & frame[ 4]) << 8) |
00436 ((0x0FF & frame[ 5]) << 0);
00437
00438 itsRCChannels[3] = ((0x0FF & frame[ 6]) << 8) |
00439 ((0x0FF & frame[ 7]) << 0);
00440
00441 itsRCChannels[4] = ((0x0FF & frame[ 8]) << 8) |
00442 ((0x0FF & frame[ 9]) << 0);
00443
00444 itsRCChannels[5] = ((0x0FF & frame[10]) << 8) |
00445 ((0x0FF & frame[11]) << 0);
00446
00447 itsRCChannels[6] = ((0x0FF & frame[12]) << 8) |
00448 ((0x0FF & frame[13]) << 0);
00449
00450 itsEmergencyMode = frame[14];
00451 if(itsRCChannels[2] > 1800)
00452 itsEmergencyMode = 255;
00453 itsRemoteMode = frame[15];
00454 itsMotor1Speed = (frame[16] - 64.0) / 64.0;
00455 itsMotor2Speed = (frame[17] - 64.0) / 64.0;
00456
00457
00458 itsLastLeftEncoder = itsLeftEncoder;
00459 itsLeftEncoder = ((0x0FF & frame[18]) << 24) |
00460 ((0x0FF & frame[19]) << 16) |
00461 ((0x0FF & frame[20]) << 8) |
00462 ((0x0FF & frame[21]) << 0);
00463
00464 itsLastRightEncoder = itsRightEncoder;
00465 itsRightEncoder =
00466 ((0x0FF & frame[22]) << 24) |
00467 ((0x0FF & frame[23]) << 16) |
00468 ((0x0FF & frame[24]) << 8) |
00469 ((0x0FF & frame[25]) << 0);
00470 if(itsRCChannels[2] < 1800){
00471 itsRcTransSpeed = (200 - ((itsRCChannels[1] - 1041) * 200)/(1874 - 1041)) -100;
00472
00473 if( itsRCChannels[6] > 1800)
00474 itsRcRotSpeed = (200 - ((itsRCChannels[0] - 963) * 200)/(1775 -963)) -100;
00475 else
00476 itsRcRotSpeed = (200 - ((itsRCChannels[0] - 1105) * 200)/(1928 -1105)) -100;
00477 double speed_cap = 100 - ((itsRCChannels[2] - 1041) * 100)/(1750 -1041);
00478 double rot_vel_cap = ((itsRCChannels[5] -900)* 100)/(2073 -900);
00479 itsTransCap = speed_cap;
00480 itsRotCap = rot_vel_cap;
00481 if(speed_cap > 100)speed_cap = 100;
00482 if(speed_cap < 0)speed_cap = 0;
00483 if(rot_vel_cap > 100)rot_vel_cap= 100;
00484 if(rot_vel_cap < 0)rot_vel_cap= 0;
00485
00486 if(itsRcTransSpeed > 100)itsRcTransSpeed = 100;
00487 if(itsRcTransSpeed < -100)itsRcTransSpeed = -100;
00488 if(itsRcRotSpeed > 100)itsRcRotSpeed= 100;
00489 if(itsRcRotSpeed < -100)itsRcRotSpeed= -100;
00490
00491 itsRcTransSpeedCapped =itsRcTransSpeed* speed_cap/100;
00492 itsRcRotSpeedCapped = itsRcRotSpeed * rot_vel_cap/-100;
00493 itsRcTransSpeed /=100.0;
00494 itsRcRotSpeed /= 100.0;
00495 itsRcTransSpeedCapped /= 100.0;
00496 itsRcRotSpeedCapped /= 100.0;
00497 LDEBUG("RC cap %f Rc rot cap %f", speed_cap,rot_vel_cap);
00498 LDEBUG("RC trans%f Rc rot %f", itsRcTransSpeed,itsRcRotSpeed);
00499 }else{
00500 itsRcTransSpeed = 0;
00501 itsRcRotSpeed = 0;
00502 itsRcTransSpeedCapped = 0;
00503 itsRcRotSpeedCapped = 0;
00504 }
00505
00506
00507 UpdatePosition();
00508
00509
00510 }
00511 else
00512 {
00513
00514 }
00515
00516 }
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535 void BeoPilot::UpdatePosition(void)
00536 {
00537 if(itsLastRightEncoder == 0.0 && itsLastLeftEncoder == 0.0)
00538 itsEncoderTimer.reset();
00539
00540 double time = (double) itsEncoderTimer.getReset()/1000000.0;
00541
00542
00543 double ticksPerMeter = 105267.836;
00544 double dr = (itsRightEncoder - itsLastRightEncoder) / ticksPerMeter;
00545 double dl = (itsLeftEncoder - itsLastLeftEncoder) / ticksPerMeter;
00546 double w = 0.51;
00547 double ot = itsPosition.z + ((dr - dl) / w );
00548 double dt = (dr + dl)/2;
00549 double xt = itsPosition.x + dt * cos(ot);
00550 double yt = itsPosition.y + dt * sin(ot);
00551
00552
00553
00554 if(time != 0.0){
00555 itsLeftMotorVelocity = -(dl/time);
00556 if(itsRemoteMode == 1)
00557 itsVelocityQue.add(itsLeftMotorVelocity/3.0);
00558 else
00559 itsVelocityQue.add(itsLeftMotorVelocity);
00560
00561 itsRightMotorVelocity = -(dr/time);
00562 }
00563 LDEBUG("Time[%f] Left V %f Right V %f,dl %f,dr %f",time,itsLeftMotorVelocity,
00564 itsRightMotorVelocity,dl,dr);
00565
00566
00567 itsDiffPosition.x = dt * cos(ot);
00568 itsDiffPosition.y = dt * sin(ot);
00569 itsDiffPosition.z = ((dr - dl) / w );
00570
00571 itsPosition.x = xt;
00572 itsPosition.y = yt;
00573 itsPosition.z = ot;
00574
00575 if(itsRemoteMode == 1)
00576 itsPosition.color = PixRGB<byte>(255,0,0);
00577 else
00578 itsPosition.color = PixRGB<byte>(0,255,0);
00579 }
00580
00581 unsigned int BeoPilot::getRCChannel(int channel)
00582 {
00583 if(channel < 0 || channel > 7)
00584 return 0;
00585
00586 unsigned char cmd[2] = {104, channel};
00587
00588 itsSerial->write(cmd, 2);
00589 std::vector<unsigned char> frame = itsSerial->readFrame(cmd[0], 255);
00590
00591 if(frame.size() == 4)
00592 {
00593 unsigned int val = ((0x0FF & frame[0]) << 24) |
00594 ((0x0FF & frame[1]) << 16) |
00595 ((0x0FF & frame[2]) << 8) |
00596 ((0x0FF & frame[3]) << 0);
00597 return val;
00598 }
00599 else
00600 LINFO("Bad Frame Size! (%lu)", frame.size());
00601
00602 return 0;
00603
00604 }
00605
00606 unsigned char BeoPilot::getRCStatus()
00607 {
00608 unsigned char cmd = 103;
00609
00610 itsSerial->write(cmd);
00611 std::vector<unsigned char> frame = itsSerial->readFrame(cmd, 255);
00612
00613 if(frame.size() == 1)
00614 return frame[0];
00615
00616 else
00617 LERROR("Bad Frame Size! (%lu)", frame.size());
00618 return 0;
00619
00620 }
00621
00622 unsigned char BeoPilot::getRCEnabled()
00623 {
00624 unsigned char cmd = 105;
00625
00626 itsSerial->write(cmd);
00627 std::vector<unsigned char> frame = itsSerial->readFrame(cmd, 255);
00628
00629 if(frame.size() == 1)
00630 return frame[0];
00631
00632 else
00633 LERROR("Bad Frame Size! (%lu)", frame.size());
00634 return 0;
00635
00636 }
00637
00638 unsigned int BeoPilot::getRCSpeed()
00639 {
00640 unsigned char cmd = 106;
00641
00642 itsSerial->write(cmd);
00643 std::vector<unsigned char> frame = itsSerial->readFrame(cmd, 255);
00644
00645 if(frame.size() == 4)
00646 {
00647 unsigned int val = ((0x0FF & frame[0]) << 24) |
00648 ((0x0FF & frame[1]) << 16) |
00649 ((0x0FF & frame[2]) << 8) |
00650 ((0x0FF & frame[3]) << 0);
00651 return val;
00652 }
00653 else
00654 LINFO("Bad Frame Size! (%lu)", frame.size());
00655
00656 return 0;
00657
00658 }
00659 void BeoPilot::resetEncoder()
00660 {
00661
00662 unsigned char cmd = 108;
00663 itsSerial->write(cmd);
00664
00665 itsPosition.x = 0;
00666 itsPosition.y = 0;
00667 itsPosition.z = 0;
00668 itsDiffPosition.x = 0;
00669 itsDiffPosition.y = 0;
00670 itsDiffPosition.z = 0;
00671
00672
00673 }
00674
00675 void BeoPilot::SetMotors(float rotationalSpeed, float translationalSpeed)
00676 {
00677
00678 if(rotationalSpeed > 1.0)
00679 rotationalSpeed = 1.0;
00680 if(rotationalSpeed < -1.0)
00681 rotationalSpeed = -1.0;
00682 if(translationalSpeed > 1.0)
00683 translationalSpeed = 1.0;
00684 if(translationalSpeed < -1.0)
00685 translationalSpeed = -1.0;
00686
00687
00688
00689
00690
00691 char rotSpeed = char(rotationalSpeed * 100.0);
00692 char tranSpeed = char(translationalSpeed * 100.0);
00693
00694
00695 unsigned char cmd[3];
00696 cmd[0] = 100;
00697 cmd[1] = rotSpeed;
00698
00699 itsSerial->write(cmd, 2);
00700
00701 usleep(10000);
00702
00703
00704 cmd[0] = 101;
00705 cmd[1] = tranSpeed;
00706
00707 itsSerial->write(cmd, 2);
00708
00709 usleep(10000);
00710 }
00711
00712
00713
00714
00715 void BeoPilot::updateGUI()
00716 {
00717 if(itsDisplayTimer.getSecs() > itsDisplayUpdateRate)
00718 {
00719 itsDisplayTimer.reset();
00720
00721 int key = itsMeterXwin.getLastKeyPress();
00722
00723 float loc_forwardSpeed = 0;
00724 float loc_rotationalSpeed = 0;
00725 bool loc_sonarProxAlert = true;
00726 float loc_sonarTime;
00727
00728 itsSpeedMutex.lock();
00729 {
00730
00731 switch(key)
00732 {
00733 case -1:
00734 break;
00735 case 25:
00736 itsForwardSpeed += .05;
00737 break;
00738 case 39:
00739 itsForwardSpeed -= .05;
00740 break;
00741 case 38:
00742 itsRotationalSpeed -= .05;
00743 break;
00744 case 40:
00745 itsRotationalSpeed += .05;
00746 break;
00747 case 65:
00748 itsForwardSpeed = 0;
00749 itsRotationalSpeed = 0;
00750 break;
00751 case 9:
00752 exit(0);
00753 break;
00754 default:
00755 LINFO("Undefined Key: %d", key);
00756 break;
00757 }
00758 if(itsMeterXwin.pressedCloseButton()) exit(0);
00759
00760 loc_forwardSpeed = itsForwardSpeed;
00761 loc_rotationalSpeed = itsRotationalSpeed;
00762 }
00763 itsSpeedMutex.unlock();
00764
00765
00766 itsSonarMutex.lock();
00767 {
00768 loc_sonarProxAlert = itsSonarProxAlert;
00769 loc_sonarTime = itsSonarTimer.getSecs();
00770 }
00771 itsSonarMutex.unlock();
00772
00773
00774 itsControlImage = Image<PixRGB<byte> >(512,256,ZEROS);
00775 writeText(itsControlImage, Point2D<int>(0,0), "Commands:", PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00776 writeText(itsControlImage, Point2D<int>(0,8), "w: Forwards", PixRGB<byte>(180,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00777 writeText(itsControlImage, Point2D<int>(0,16), "s: Backwards", PixRGB<byte>(180,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00778 writeText(itsControlImage, Point2D<int>(0,24), "a: Left", PixRGB<byte>(180,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00779 writeText(itsControlImage, Point2D<int>(0,32), "d: Right", PixRGB<byte>(180,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00780 writeText(itsControlImage, Point2D<int>(0,40), "space: STOP", PixRGB<byte>(180,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00781 writeText(itsControlImage, Point2D<int>(0,48), "esc: quit", PixRGB<byte>(180,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00782
00783 char buffer[128];
00784 sprintf(buffer, "Forward Speed: %2.2f%% Right: %1.3f m/s Left: %1.3f m/s", loc_forwardSpeed*100.0,itsRightMotorVelocity,itsLeftMotorVelocity);
00785 writeText(itsControlImage, Point2D<int>(0,60), buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(8));
00786
00787 sprintf(buffer, "Rotational Speed: %0.2f -> %0.2f", loc_rotationalSpeed,
00788 loc_rotationalSpeed *itsRotCap/100.0);
00789 writeText(itsControlImage, Point2D<int>(0,75), buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(8));
00790
00791 sprintf(buffer, "Right Encoder: %d", itsRightEncoder);
00792 writeText(itsControlImage, Point2D<int>(0,90), buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00793
00794 sprintf(buffer, "Left Encoder: %d", itsLeftEncoder);
00795 writeText(itsControlImage, Point2D<int>(0,98), buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00796
00797 sprintf(buffer, "Enc X: %fm",itsPosition.x );
00798 writeText(itsControlImage, Point2D<int>(0,116), buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00799
00800 sprintf(buffer, "Enc Y: %fm",itsPosition.y );
00801 writeText(itsControlImage, Point2D<int>(0,124), buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00802
00803 sprintf(buffer, "Enc R: %f",itsPosition.z );
00804 writeText(itsControlImage, Point2D<int>(0,132), buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00805
00806 if(itsLoadFromLogFile){
00807 sprintf(buffer, "LEn X: %fm",itsLogPosition.x );
00808 writeText(itsControlImage, Point2D<int>(0,140), buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00809
00810 sprintf(buffer, "LEn Y: %fm",itsLogPosition.y );
00811 writeText(itsControlImage, Point2D<int>(0,148), buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00812
00813 sprintf(buffer, "LEn R: %f",itsLogPosition.z );
00814 writeText(itsControlImage, Point2D<int>(0,156), buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00815 }
00816
00817
00818
00819 sprintf(buffer, "Sonar Timer: %0.2fs", loc_sonarTime);
00820 writeText(itsControlImage, Point2D<int>(256,0), buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(8));
00821
00822 PixRGB<byte> proxAlertColor;
00823 if(loc_sonarProxAlert)
00824 {
00825 sprintf(buffer, "Proximity Alert!");
00826 proxAlertColor = PixRGB<byte>(255,0,0);
00827 }
00828 else
00829 {
00830 sprintf(buffer, "Sonar OK");
00831 proxAlertColor = PixRGB<byte>(20,128,20);
00832 }
00833 writeText(itsControlImage, Point2D<int>(256,15), buffer, proxAlertColor, PixRGB<byte>(0,0,0),SimpleFont::FIXED(8));
00834
00835
00836 PixRGB<byte> serialOkColor;
00837 int code = itsSerial->getSerialErrno();
00838 if(code==0||code==15)
00839 {
00840 sprintf(buffer, "Serial OK");
00841 serialOkColor = PixRGB<byte>(20,128,20);
00842 }
00843 else
00844 {
00845 sprintf(buffer, "Serial Disconnected!");
00846 serialOkColor = PixRGB<byte>(255,0,0);
00847 }
00848 writeText(itsControlImage, Point2D<int>(256,30), buffer, serialOkColor, PixRGB<byte>(0,0,0),SimpleFont::FIXED(8));
00849
00850
00851 for(size_t i=0; i<itsChannelMeters.size(); i++)
00852 {
00853
00854 sprintf(buffer, "Channel%lu: %d", i+1, itsRCChannels[i]);
00855
00856 Point2D<int> pastePoint = Point2D<int>(
00857 int(itsChannelMeters[0].getWidth()*itsChannelMeters.size()*1.05+20),
00858 itsControlImage.getHeight() - itsChannelMeters[i].getHeight() - 10 + i*8
00859 );
00860
00861 writeText(itsControlImage, pastePoint, buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00862
00863 pastePoint = Point2D<int>(
00864 int(10+itsChannelMeters[i].getWidth()*i*1.05),
00865 itsControlImage.getHeight() - itsChannelMeters[i].getHeight() - 10
00866 );
00867 inplacePaste(itsControlImage, itsChannelMeters[i].render(itsRCChannels[i]), pastePoint );
00868 }
00869
00870 sprintf(buffer, "Emergency Mode: %d", itsEmergencyMode);
00871 writeText(itsControlImage, Point2D<int>(256,88), buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00872
00873 sprintf(buffer, "RemoteMode: %d", itsRemoteMode);
00874 writeText(itsControlImage, Point2D<int>(256,96), buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00875
00876 if(itsLoadFromLogFile){
00877 sprintf(buffer, "Log Mode: %d", itsLogRemoteMode);
00878 writeText(itsControlImage, Point2D<int>(340,96), buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00879 }
00880 sprintf(buffer, "Motor 1 Speed: %0.2f", itsMotor1Speed);
00881 writeText(itsControlImage, Point2D<int>(256,104), buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00882
00883 sprintf(buffer, "Motor 2 Speed: %0.2f", itsMotor2Speed);
00884 writeText(itsControlImage, Point2D<int>(256,112), buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00885
00886 sprintf(buffer, "RC Speed : %0.2f -> %0.2f", itsRcTransSpeed,itsRcTransSpeedCapped);
00887 writeText(itsControlImage, Point2D<int>(256,120), buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00888
00889 sprintf(buffer, "RC Rotation: %0.2f -> %0.2f", itsRcRotSpeed,itsRcRotSpeedCapped);
00890 writeText(itsControlImage, Point2D<int>(256,128), buffer, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),SimpleFont::FIXED(6));
00891
00892
00893
00894
00895
00896
00897 inplacePaste(itsDispImage,itsControlImage,Point2D<int>(0,0));
00898
00899
00900
00901
00902 int w = itsMapImage.getWidth();
00903 int h = itsMapImage.getHeight();
00904 double scaleRate = 0.9;
00905 Point2D<int> drawPos(
00906 int(itsPosition.x*itsMapScale + w/2),
00907 int(itsPosition.y*itsMapScale + h/2)
00908 );
00909 if(itsMapImage.coordsOk(drawPos))
00910 {
00911 itsPositionMap.push_back(itsPosition);
00912 }else
00913 {
00914
00915 do{
00916 itsMapScale *= scaleRate;
00917 drawPos = Point2D<int>(
00918 int(itsPosition.x*itsMapScale + w/2),
00919 int(itsPosition.y*itsMapScale + h/2)
00920 );
00921 }while(!itsMapImage.coordsOk(drawPos));
00922 reDrawMap(itsMapScale);
00923 }
00924 itsMapImage.setVal(drawPos, itsPosition.color);
00925
00926 Image<PixRGB<byte> > itsDrawMapImage(itsMapImage);
00927 drawCircle(itsDrawMapImage, drawPos, 7, PixRGB<byte>(255,255,255));
00928 drawLine(itsDrawMapImage, drawPos,-itsPosition.z, 7, PixRGB<byte>(255,255,255));
00929
00930 if(itsLoadFromLogFile){
00931 Point2D<int> drawPos2(
00932 int(itsLogPosition.x*itsMapScale + w/2),
00933 int(itsLogPosition.y*itsMapScale + h/2)
00934 );
00935 if(!itsMapImage.coordsOk(drawPos2))
00936 {
00937
00938 do{
00939 itsMapScale *= scaleRate;
00940 drawPos2 = Point2D<int>(
00941 int(itsLogPosition.x*itsMapScale + w/2),
00942 int(itsLogPosition.y*itsMapScale + h/2)
00943 );
00944 }while(!itsMapImage.coordsOk(drawPos2));
00945 reDrawMap(itsMapScale);
00946 }
00947
00948 if(itsReplaySpeed.getVal() != 1)
00949 reDrawMap(itsMapScale);
00950 itsMapImage.setVal(drawPos2, itsLogPosition.color);
00951 drawCircle(itsDrawMapImage, drawPos2, 7, PixRGB<byte>(0,255,0));
00952 drawLine(itsDrawMapImage, drawPos2,-itsLogPosition.z, 7, PixRGB<byte>(255,255,255));
00953 }
00954 inplacePaste(itsDispImage,itsDrawMapImage,Point2D<int>(0,256));
00955
00956 std::vector<std::vector<float> > lines;
00957 lines.push_back(itsVelocityQue.getVector());
00958 lines.push_back(itsVelocityTargetQue.getVector());
00959
00960 std::vector<PixRGB<byte> > linesColor;
00961 linesColor.push_back(PixRGB<byte>(255,0,0));
00962 linesColor.push_back(PixRGB<byte>(255,165,0));
00963
00964 Image<PixRGB<byte> > plotImage = multilinePlot(
00965 lines,
00966 288+70,256,
00967 -1.0f,1.0f,
00968 "velocity","m/s","",
00969 linesColor,
00970 PixRGB<byte>(255,255,255),
00971 PixRGB<byte>(0,0,0)
00972
00973 );
00974 inplacePaste(itsDispImage,plotImage,Point2D<int>(512-70,0));
00975
00976
00977 drawLine(itsDispImage,Point2D<int>(0,255),Point2D<int>(800,255),PixRGB<byte>(255,255,255));
00978 drawLine(itsDispImage,Point2D<int>(512-70,0),Point2D<int>(512-70,255),PixRGB<byte>(255,255,255));
00979
00980
00981 inplacePaste(itsDispImage,itsDispCameraImage,Point2D<int>(itsDispImage.getWidth()-320,itsDispImage.getHeight()-240));
00982
00983 itsMeterXwin.drawImage(itsDispImage);
00984
00985 }
00986 }
00987 void BeoPilot::reDrawMap(double scale)
00988 {
00989
00990
00991 itsMapImage = Image<PixRGB<byte> >(800,344,ZEROS);
00992
00993 int w = itsMapImage.getWidth();
00994 int h = itsMapImage.getHeight();
00995
00996
00997 for(int i = 0;i < (int)itsLogPositionMap.size();i++)
00998 {
00999 Point2D<int> tmp(
01000
01001 int(itsLogPositionMap[i].x*scale + w/2),
01002 int(itsLogPositionMap[i].y*scale + h/2)
01003 );
01004 if(itsMapImage.coordsOk(tmp))
01005 itsMapImage.setVal(tmp, itsLogPositionMap[i].color);
01006 }
01007 for(int i = 0;i < (int)itsPositionMap.size();i++)
01008 {
01009 Point2D<int> tmp(
01010
01011 int(itsPositionMap[i].x*scale + w/2),
01012 int(itsPositionMap[i].y*scale + h/2)
01013 );
01014 if(itsMapImage.coordsOk(tmp))
01015 itsMapImage.setVal(tmp, itsPositionMap[i].color);
01016 }
01017
01018 }
01019
01020 void BeoPilot::updateMessage(const RobotSimEvents::EventMessagePtr& eMsg,
01021 const Ice::Current&)
01022 {
01023 if(eMsg->ice_isA("::BeobotEvents::MotorRequest"))
01024 {
01025 itsSpeedMutex.lock();
01026 {
01027 BeobotEvents::MotorRequestPtr mrMsg = BeobotEvents::MotorRequestPtr::dynamicCast(eMsg);
01028 itsForwardSpeedReq = mrMsg->transVel;
01029 itsRotationalSpeedReq = mrMsg->rotVel;
01030 }
01031 itsSpeedMutex.unlock();
01032 LINFO("Received Motor Request Speed:[%f] Rotation:[%f]",itsForwardSpeedReq,itsRotationalSpeedReq);
01033 }
01034 else if(eMsg->ice_isA("::BeobotEvents::SonarMessage"))
01035 {
01036 itsSonarMutex.lock();
01037 {
01038 itsSonarTimer.reset();
01039 BeobotEvents::SonarMessagePtr srMsg = BeobotEvents::SonarMessagePtr::dynamicCast(eMsg);
01040 itsSonarReadings = srMsg->distances;
01041 itsSonarAngles = srMsg->angles;
01042 }
01043 itsSonarMutex.unlock();
01044 }
01045 }
01046
01047
01048 void BeoPilot::getCurrentLogData()
01049 {
01050 uint64 time = itsLogTimer.get()/1000.0;
01051 if(itsReplaySpeed.getVal()==1)
01052 {
01053 do{
01054 if(itsLogData[itsCurrentTimeIndex].time < time && itsCurrentTimeIndex < (int)itsLogData.size())
01055 itsCurrentTimeIndex++;
01056 }while(itsLogData[itsCurrentTimeIndex].time < time && itsCurrentTimeIndex < (int)itsLogData.size());
01057 }
01058 if((int)itsLogImageData.size() != 0){
01059 do{
01060 if(itsLogImageData[itsCurrentTimeIndex2].time < time && itsCurrentTimeIndex2 < (int)itsLogImageData.size())
01061 itsCurrentTimeIndex2++;
01062 }while(itsLogImageData[itsCurrentTimeIndex2].time < time && itsCurrentTimeIndex2 < (int)itsLogImageData.size());
01063 imageData img = itsLogImageData[itsCurrentTimeIndex2];
01064 if(file_exists(img.imagePath.c_str()))
01065 itsDispCameraImage = Raster::ReadRGB(img.imagePath);
01066 LINFO("Found Index[%d] with Image[%f],Path %s",itsCurrentTimeIndex2,itsLogImageData[itsCurrentTimeIndex2].time,itsLogImageData[itsCurrentTimeIndex2].imagePath.c_str()) ;
01067 }
01068 LINFO("Current Time[%f] Found Index[%d] with LogTimeStamp[%f]",(double)time,itsCurrentTimeIndex,itsLogData[itsCurrentTimeIndex].time) ;
01069
01070 for(int i = 0;i < itsReplaySpeed.getVal();i++)
01071 {
01072 if(itsReplaySpeed.getVal() !=1 && itsCurrentTimeIndex < (int)itsLogData.size())
01073 itsCurrentTimeIndex++;
01074
01075 motorData tmp = itsLogData[itsCurrentTimeIndex];
01076
01077
01078
01079
01080
01081
01082
01083 itsForwardSpeed = tmp.rcTransVel;
01084 itsRotationalSpeed = tmp.rcRotVel;
01085
01086 itsLogDiffPosition.x = tmp.encoderX;
01087 itsLogDiffPosition.y = tmp.encoderY;
01088 itsLogDiffPosition.z = tmp.encoderOri;
01089
01090 itsLogPosition.x += itsLogDiffPosition.x;
01091 itsLogPosition.y += itsLogDiffPosition.y;
01092 itsLogPosition.z += itsLogDiffPosition.z;
01093
01094 itsRcTransSpeed = tmp.rcTransVel;
01095 itsRcRotSpeed = tmp.rcRotVel ;
01096 itsLogRemoteMode = tmp.rcMode ;
01097
01098 itsMotor1Speed = itsForwardSpeed - itsRotationalSpeed;
01099 itsMotor2Speed = itsForwardSpeed + itsRotationalSpeed;
01100 if(itsLogRemoteMode == 1)
01101 itsLogPosition.color = PixRGB<byte>(255,0,0);
01102 else
01103 itsLogPosition.color = PixRGB<byte>(0,255,0);
01104
01105 if(itsCurrentTimeIndex <(int)itsLogData.size())
01106 itsLogPositionMap.push_back(itsLogPosition);
01107 }
01108 }
01109 void BeoPilot::drawAllMap(void)
01110 {
01111 for(int i = 0;i < (int)itsLogData.size();i++){
01112 motorData tmp = itsLogData[i];
01113 itsLogDiffPosition.x = tmp.encoderX;
01114 itsLogDiffPosition.y = tmp.encoderY;
01115 itsLogDiffPosition.z = tmp.encoderOri;
01116
01117 itsLogPosition.x += itsLogDiffPosition.x;
01118 itsLogPosition.y += itsLogDiffPosition.y;
01119 itsLogPosition.z += itsLogDiffPosition.z;
01120 itsLogPositionMap.push_back(itsLogPosition);
01121 }
01122 }