EstimationNode.cpp
Go to the documentation of this file.
00001 
00023 #include "EstimationNode.h"
00024 #include "ros/ros.h"
00025 #include "ros/package.h"
00026 #include "geometry_msgs/Twist.h"
00027 #include "sensor_msgs/Image.h"
00028 #include "tf/tfMessage.h"
00029 #include "tf/transform_listener.h"
00030 #include "tf/transform_broadcaster.h"
00031 #include "std_msgs/Empty.h"
00032 #include "std_srvs/Empty.h"
00033 #include "../HelperFunctions.h"
00034 #include "DroneKalmanFilter.h"
00035 #include <ardrone_autonomy/Navdata.h>
00036 #include "deque"
00037 #include "uga_tum_ardrone/filter_state.h"
00038 #include "PTAMWrapper.h"
00039 #include "std_msgs/String.h"
00040 #include "std_msgs/Empty.h"
00041 #include "std_srvs/Empty.h"
00042 #include "MapView.h"
00043 #include <sys/stat.h>
00044 #include <string>
00045 
00046 using namespace std;
00047 
00048 pthread_mutex_t EstimationNode::logIMU_CS = PTHREAD_MUTEX_INITIALIZER;
00049 pthread_mutex_t EstimationNode::logPTAM_CS = PTHREAD_MUTEX_INITIALIZER;
00050 pthread_mutex_t EstimationNode::logFilter_CS = PTHREAD_MUTEX_INITIALIZER;
00051 pthread_mutex_t EstimationNode::logPTAMRaw_CS = PTHREAD_MUTEX_INITIALIZER;
00052 
00053 EstimationNode::EstimationNode()
00054 {
00055     navdata_channel = nh_.resolveName("ardrone/navdata");
00056     control_channel = nh_.resolveName("cmd_vel");
00057     output_channel = nh_.resolveName("ardrone/predictedPose");
00058     video_channel = nh_.resolveName("ardrone/image_raw");
00059     command_channel = nh_.resolveName("uga_tum_ardrone/com");
00060         packagePath = ros::package::getPath("uga_tum_ardrone");
00061 
00062         std::string val;
00063         float valFloat = 0;
00064 
00065         predTime = ros::Duration(25*0.001);
00066 
00067         ros::param::get("~publishFreq", val);
00068         if(val.size()>0)
00069                 sscanf(val.c_str(), "%f", &valFloat);
00070         else
00071                 valFloat = 30;
00072         publishFreq = valFloat;
00073         cout << "set publishFreq to " << valFloat << "Hz"<< endl;
00074 
00075 
00076 
00077         ros::param::get("~calibFile", calibFile);
00078         if(calibFile.size()>0)
00079                 cout << "set calibFile to " << calibFile << endl;
00080         else
00081                 cout << "set calibFile to DEFAULT" << endl;
00082 
00083 
00084         navdata_sub       = nh_.subscribe(navdata_channel, 10, &EstimationNode::navdataCb, this);
00085         vel_sub          = nh_.subscribe(control_channel,10, &EstimationNode::velCb, this);
00086         vid_sub          = nh_.subscribe(video_channel,10, &EstimationNode::vidCb, this);
00087 
00088         dronepose_pub      = nh_.advertise<uga_tum_ardrone::filter_state>(output_channel,1);
00089 
00090         uga_tum_ardrone_pub        = nh_.advertise<std_msgs::String>(command_channel,50);
00091         uga_tum_ardrone_sub        = nh_.subscribe(command_channel,50, &EstimationNode::comCb, this);
00092 
00093         //tf_broadcaster();
00094 
00095         // other internal vars
00096         logfileIMU = logfilePTAM = logfileFilter = logfilePTAMRaw = 0;
00097         currentLogID = 0;
00098         lastDroneTS = 0;
00099         lastRosTS = 0;
00100         droneRosTSOffset = 0;
00101         lastNavStamp = ros::Time(0);
00102         filter = new DroneKalmanFilter(this);
00103         ptamWrapper = new PTAMWrapper(filter, this);
00104         mapView = new MapView(filter, ptamWrapper, this);
00105         arDroneVersion = 0;
00106         //memset(&lastNavdataReceived,0,sizeof(ardrone_autonomy::Navdata));
00107 
00108     initialYaw = 0;
00109 
00110 }
00111 
00112 EstimationNode::~EstimationNode()
00113 {
00114         filter->release();
00115         delete mapView;
00116         delete ptamWrapper;
00117         delete filter;
00118 
00119 
00120         //delete infoQueue;
00121 }
00122 void EstimationNode::navdataCb(const ardrone_autonomy::NavdataConstPtr navdataPtr)
00123 {
00124         lastNavdataReceived = *navdataPtr;
00125         if(ros::Time::now() - lastNavdataReceived.header.stamp > ros::Duration(30.0))
00126                 lastNavdataReceived.header.stamp = ros::Time::now();
00127 
00128         if(arDroneVersion == 0)
00129         {
00130                 arDroneVersion = (navdataPtr->pressure == 0) ? 1 : 2;
00131                 std::cout <<"Found ARDrone Version " << arDroneVersion << std::endl;
00132         }
00133 
00134 
00135         // darn ROS really messes up timestamps.
00136         // they should arrive every 5ms, with occasionally dropped packages.
00137         // instead, they arrive with gaps of up to 30ms, and then 6 packages with the same timestamp.
00138         // so: this procedure "smoothes out" received package timestamps, shifting their timestamp by max. 20ms to better fit the order.
00139         long rosTS = getMS(lastNavdataReceived.header.stamp);
00140         long droneTS = navdataPtr->tm / 1000;
00141 
00142         if(lastDroneTS == 0) lastDroneTS = droneTS;
00143 
00144         if((droneTS+1000000) < lastDroneTS)
00145         {
00146                 droneRosTSOffset = rosTS - droneTS;     // timestamp-overflow, reset running average.
00147                 ROS_WARN("Drone Navdata timestamp overflow! (should happen epprox every 30min, while drone switched on)");
00148         }
00149         else
00150                 droneRosTSOffset = 0.9 * droneRosTSOffset + 0.1*(rosTS - droneTS);
00151 
00152         long rosTSNew =droneTS + droneRosTSOffset;      // this should be the correct timestamp.
00153         long TSDiff = std::min(100l,std::max(-100l,rosTSNew-rosTS));    // never change by more than 100ms.
00154         lastNavdataReceived.header.stamp += ros::Duration(TSDiff/1000.0);       // change!
00155         lastRosTS = rosTS;
00156         lastDroneTS = droneTS;
00157 
00158 
00159         // convert to originally sent drone values (undo ardrone_autonomy changes)
00160         lastNavdataReceived.rotZ *= -1; // yaw inverted
00161         lastNavdataReceived.rotY *= -1; // pitch inverted
00162         lastNavdataReceived.vy *= -1;   // yaw inverted
00163         lastNavdataReceived.vz *= -1;   // pitch inverted
00164         lastNavdataReceived.ay *= -1;   // yaw inverted
00165         lastNavdataReceived.az *= -1;   // pitch inverted
00166 
00167 
00168 
00169         // push back in filter queue.
00170         pthread_mutex_lock( &filter->filter_CS );
00171         filter->navdataQueue->push_back(lastNavdataReceived);
00172         pthread_mutex_unlock( &filter->filter_CS );
00173 
00174 
00175         // give to PTAM (for scale estimation)
00176         ptamWrapper->newNavdata(&lastNavdataReceived);
00177 
00178 
00179         // save last timestamp
00180         if(lastNavStamp != ros::Time(0) && (lastNavdataReceived.header.stamp - lastNavStamp > ros::Duration(0.1)))
00181                 std::cout << (lastNavdataReceived.header.stamp - lastNavStamp).toSec() << "s between two consecutive navinfos. This system requires Navinfo at 200Hz. If this error persists, set drone to debug mode and change publish freq in ardrone_autonomy" << std::endl;
00182         lastNavStamp = lastNavdataReceived.header.stamp;
00183 
00184 
00185         if(logfileIMU != NULL)
00186         {
00187                 int pingNav = 0, pingVid = 0;
00188                 pthread_mutex_lock(&logIMU_CS);
00189                 if(logfileIMU != NULL)
00190                         (*logfileIMU) << getMS(lastNavdataReceived.header.stamp) << " " << lastNavdataReceived.tm << " " <<
00191                         lastNavdataReceived.vx << " " << lastNavdataReceived.vy << " " << lastNavdataReceived.altd << " " << lastNavdataReceived.rotX/1000.0 << " " << lastNavdataReceived.rotY/1000.0 << " " << lastNavdataReceived.rotZ/1000.0 << " " <<
00192                         lastNavdataReceived.pressure << " " <<  0 << " " <<  0 << " " << 0 << " " <<    // control: roll pitch gaz yaw.
00193                         pingNav << " " << pingVid << "\n";
00194                 pthread_mutex_unlock(&logIMU_CS);
00195         }
00196 
00197 }
00198 
00199 void EstimationNode::velCb(const geometry_msgs::TwistConstPtr velPtr)
00200 {
00201         geometry_msgs::TwistStamped ts;
00202         ts.header.stamp = ros::Time::now();
00203         ts.twist = *velPtr;
00204 
00205         // for some reason this needs to be inverted.
00206         // linear.y corresponds to ROLL
00207         ts.twist.linear.y *= -1;
00208         ts.twist.linear.x *= -1;
00209         ts.twist.angular.z *= -1;
00210 
00211         pthread_mutex_lock( &filter->filter_CS );
00212         filter->velQueue->push_back(ts);
00213         pthread_mutex_unlock( &filter->filter_CS );
00214 }
00215 
00216 void EstimationNode::vidCb(const sensor_msgs::ImageConstPtr img)
00217 {
00218         // give to PTAM
00219         ptamWrapper->newImage(img);
00220 }
00221 
00222 void EstimationNode::comCb(const std_msgs::StringConstPtr str)
00223 {
00224         if(str->data.length() > 2 && str->data.substr(0,2) == "p ")
00225         {
00226                 ptamWrapper->handleCommand(str->data.substr(2,str->data.length()-2));
00227         }
00228 
00229         if(str->data.length() > 2 && str->data.substr(0,2) == "f ")
00230         {
00231                 mapView->handleCommand(str->data.substr(2,str->data.length()-2));
00232         }
00233 
00234         if(str->data.length() > 2 && str->data.substr(0,2) == "m ")
00235         {
00236                 mapView->handleCommand(str->data.substr(2,str->data.length()-2));
00237         }
00238 
00239         if(str->data.length() == 9 && str->data.substr(0,9) == "toggleLog")
00240         {
00241                 this->toogleLogging();
00242         }
00243 
00244         // hack to handle the setinitialstate command
00245 
00246                 // only handle commands with prefix c
00247         if(str->data.length() > 2 && str->data.substr(0,2) == "c ")
00248         {
00249 
00250                 float parameter;
00251                 // setInitialYaw
00252                 if(sscanf(str->data.c_str(),"c setInitialYaw %f",&parameter) == 1)
00253                 {
00254                         initialYaw = parameter;
00255                 }
00256         }
00257 
00258 
00259         int a, b;
00260         if(sscanf(str->data.c_str(),"pings %d %d",&a, &b) == 2)
00261         {
00262                 filter->setPing((unsigned int)a, (unsigned int)b);
00263                 predTime = ros::Duration((0.001*filter->delayControl)); // set predTime to new delayControl
00264         }
00265 }
00266 
00267 
00268 void EstimationNode::Loop()
00269 {
00270           ros::Rate pub_rate(publishFreq);
00271 
00272           ros::Time lastInfoSent = ros::Time::now();
00273 
00274           while (nh_.ok())
00275           {
00276                   // -------------- 1. put nav & control in internal queues. ---------------
00277                   ros::spinOnce();
00278 
00279 
00280                   // -------------- 3. get predicted pose and publish! ---------------
00281                   // get filter state msg
00282                   pthread_mutex_lock( &filter->filter_CS );
00283                   uga_tum_ardrone::filter_state s = filter->getPoseAt(ros::Time().now() + predTime);
00284                   pthread_mutex_unlock( &filter->filter_CS );
00285 
00286                   // fill metadata
00287                   s.header.stamp = ros::Time().now();
00288                   s.scale = filter->getCurrentScales()[0];
00289                   s.scaleAccuracy = filter->getScaleAccuracy();
00290                   s.ptamState = ptamWrapper->PTAMStatus;
00291                   s.droneState = lastNavdataReceived.state;
00292                   s.batteryPercent = lastNavdataReceived.batteryPercent;
00293 
00294                   // publish!
00295                   dronepose_pub.publish(s);
00296 
00297 
00298                   // --------- if need be: add fake PTAM obs --------
00299                   // if PTAM updates hang (no video or e.g. init), filter is never permanently rolled forward -> queues get too big.
00300                   // dont allow this to happen by faking a ptam observation if queue gets too big (500ms = 100 observations)
00301                   if((getMS(ros::Time().now()) - filter->predictdUpToTimestamp) > 500)
00302                           filter->addFakePTAMObservation(getMS(ros::Time().now()) - 300);
00303 
00304 
00305                   // ---------- maybe send new info --------------------------
00306                   if((ros::Time::now() - lastInfoSent) > ros::Duration(0.4))
00307                   {
00308                           reSendInfo();
00309                           lastInfoSent = ros::Time::now();
00310                   }
00311 
00312                   // -------------- 4. sleep until rate is hit. ---------------
00313                   pub_rate.sleep();
00314           }
00315 }
00316 void EstimationNode::dynConfCb(uga_tum_ardrone::StateestimationParamsConfig &config, uint32_t level)
00317 {
00318         if(!filter->allSyncLocked && config.PTAMSyncLock)
00319                 ROS_WARN("Ptam Sync has been disabled. This fixes scale etc.");
00320 
00321         if(!ptamWrapper->mapLocked && config.PTAMMapLock)
00322                 ROS_WARN("Ptam Map has been locked.");
00323 
00324 
00325         filter->useControl =config.UseControlGains;
00326         filter->usePTAM =config.UsePTAM;
00327         filter->useNavdata =config.UseNavdata;
00328 
00329         filter->useScalingFixpoint = config.RescaleFixOrigin;
00330 
00331         ptamWrapper->maxKF = config.PTAMMaxKF;
00332         ptamWrapper->mapLocked = config.PTAMMapLock;
00333         filter->allSyncLocked = config.PTAMSyncLock;
00334 
00335     ptamWrapper->setPTAMPars(config.PTAMMinKFTimeDiff, config.PTAMMinKFWiggleDist, config.PTAMMinKFDist,
00336                              config.MinTolerance, config.MaxTolerance);
00337 
00338         filter->c1 = config.c1;
00339         filter->c2 = config.c2;
00340         filter->c3 = config.c3;
00341         filter->c4 = config.c4;
00342         filter->c5 = config.c5;
00343         filter->c6 = config.c6;
00344         filter->c7 = config.c7;
00345         filter->c8 = config.c8;
00346 
00347         filter->zDriftThreshold = config.zDriftThreshold;
00348         filter->yawDriftThreshold = config.yawDriftThreshold;
00349 
00350 }
00351 
00352 pthread_mutex_t EstimationNode::uga_tum_ardrone_CS = PTHREAD_MUTEX_INITIALIZER; //pthread_mutex_lock( &cs_mutex );
00353 void EstimationNode::publishCommand(std::string c)
00354 {
00355         std_msgs::String s;
00356         s.data = c.c_str();
00357         pthread_mutex_lock(&uga_tum_ardrone_CS);
00358         uga_tum_ardrone_pub.publish(s);
00359         pthread_mutex_unlock(&uga_tum_ardrone_CS);
00360 }
00361 
00362 void EstimationNode::publishTf(TooN::SE3<> trans, ros::Time stamp, int seq, std::string system)
00363 {
00364         trans = trans.inverse();
00365 
00366         tf::Matrix3x3 m;
00367         m[0][0] = trans.get_rotation().get_matrix()(0,0);
00368         m[0][1] = trans.get_rotation().get_matrix()(0,1);
00369         m[0][2] = trans.get_rotation().get_matrix()(0,2);
00370         m[1][0] = trans.get_rotation().get_matrix()(1,0);
00371         m[1][1] = trans.get_rotation().get_matrix()(1,1);
00372         m[1][2] = trans.get_rotation().get_matrix()(1,2);
00373         m[2][0] = trans.get_rotation().get_matrix()(2,0);
00374         m[2][1] = trans.get_rotation().get_matrix()(2,1);
00375         m[2][2] = trans.get_rotation().get_matrix()(2,2);
00376 
00377         tf::Vector3 v;
00378         v[0] = trans.get_translation()[0];
00379         v[1] = trans.get_translation()[1];
00380         v[2] = trans.get_translation()[2];
00381 
00382 
00383         tf::Transform tr = tf::Transform(m,v);
00384         tf::StampedTransform t = tf::StampedTransform(tr,stamp,"map",system);
00385         tf_broadcaster.sendTransform(t);
00386 
00387 
00388 
00389         if(logfilePTAMRaw != NULL)
00390         {
00391                 pthread_mutex_lock(&(logPTAMRaw_CS));
00392                 // log:
00393                 // - filterPosePrePTAM estimated for videoFrameTimestamp-delayVideo.
00394                 // - PTAMResulttransformed estimated for videoFrameTimestamp-delayVideo. (using imu only for last step)
00395                 // - predictedPoseSpeed estimated for lastNfoTimestamp+filter->delayControl     (actually predicting)
00396                 // - predictedPoseSpeedATLASTNFO estimated for lastNfoTimestamp (using imu only)
00397                 if(logfilePTAMRaw != NULL)
00398                         (*(logfilePTAMRaw)) << seq << " " << stamp << " " << tr.getOrigin().x() << " " << tr.getOrigin().y() << " " << tr.getOrigin().z() << " " <<
00399                         tr.getRotation().x() << " " << tr.getRotation().y() << " " << tr.getRotation().z() << " " << tr.getRotation().w() << std::endl;
00400 
00401                 pthread_mutex_unlock(&(logPTAMRaw_CS));
00402         }
00403 
00404 }
00405 
00406 void EstimationNode::toogleLogging()
00407 {
00408         // first: always check for /log dir
00409         struct stat st;
00410         if(stat((packagePath+std::string("/logs")).c_str(),&st) != 0)
00411                 mkdir((packagePath+std::string("/logs")).c_str(),S_IXGRP | S_IXOTH | S_IXUSR | S_IRWXU | S_IRWXG | S_IROTH);
00412 
00413         char buf[200];
00414         bool quitLogging = false;
00415         if(logfileIMU == 0)
00416         {
00417                 currentLogID = ((long)time(0))*100+(getMS()%100);               // time(0) + ms
00418                 startedLogClock = getMS();
00419                 ROS_INFO("\n\nENABLED LOGGING to %s/logs/%ld\n\n\n",packagePath.c_str(),currentLogID);
00420                 sprintf(buf,"%s/logs/%ld",packagePath.c_str(),currentLogID);
00421                 mkdir(buf, S_IXGRP | S_IXOTH | S_IXUSR | S_IRWXU | S_IRWXG | S_IROTH);
00422 
00423 
00424                 sprintf(buf,"u l ENABLED LOGGING to %s/logs/%ld",packagePath.c_str(),currentLogID);
00425                 publishCommand(buf);
00426         }
00427         else
00428                 quitLogging = true;
00429 
00430 
00431 
00432         // IMU
00433         pthread_mutex_lock(&logIMU_CS);
00434         if(logfileIMU == 0)
00435         {
00436                 logfileIMU = new std::ofstream();
00437                 sprintf(buf,"%s/logs/%ld/logIMU.txt",packagePath.c_str(),currentLogID);
00438                 logfileIMU->open (buf);
00439         }
00440         else
00441         {
00442                 logfileIMU->flush();
00443                 logfileIMU->close();
00444                 delete logfileIMU;
00445                 logfileIMU = NULL;
00446         }
00447         pthread_mutex_unlock(&logIMU_CS);
00448 
00449 
00450         // IMU
00451         pthread_mutex_lock(&logPTAM_CS);
00452         if(logfilePTAM == 0)
00453         {
00454                 logfilePTAM = new std::ofstream();
00455                 sprintf(buf,"%s/logs/%ld/logPTAM.txt",packagePath.c_str(),currentLogID);
00456                 logfilePTAM->open (buf);
00457         }
00458         else
00459         {
00460                 logfilePTAM->flush();
00461                 logfilePTAM->close();
00462                 delete logfilePTAM;
00463                 logfilePTAM = NULL;
00464         }
00465         pthread_mutex_unlock(&logPTAM_CS);
00466 
00467 
00468 
00469         // IMU
00470         pthread_mutex_lock(&logFilter_CS);
00471         if(logfileFilter == 0)
00472         {
00473                 logfileFilter = new std::ofstream();
00474                 sprintf(buf,"%s/logs/%ld/logFilter.txt",packagePath.c_str(),currentLogID);
00475                 logfileFilter->open (buf);
00476         }
00477         else
00478         {
00479                 logfileFilter->flush();
00480                 logfileFilter->close();
00481                 delete logfileFilter;
00482                 logfileFilter = NULL;
00483         }
00484         pthread_mutex_unlock(&logFilter_CS);
00485 
00486 
00487         // IMU
00488         pthread_mutex_lock(&logPTAMRaw_CS);
00489         if(logfilePTAMRaw == 0)
00490         {
00491                 logfilePTAMRaw = new std::ofstream();
00492                 sprintf(buf,"%s/logs/%ld/logPTAMRaw.txt",packagePath.c_str(),currentLogID);
00493                 logfilePTAMRaw->open (buf);
00494         }
00495         else
00496         {
00497                 logfilePTAMRaw->flush();
00498                 logfilePTAMRaw->close();
00499                 delete logfilePTAMRaw;
00500                 logfilePTAMRaw = NULL;
00501         }
00502         pthread_mutex_unlock(&logPTAMRaw_CS);
00503 
00504 
00505         if(quitLogging)
00506         {
00507                 printf("\n\nDISABLED LOGGING (logged %ld sec)\n\n\n",(getMS()-startedLogClock+500)/1000);
00508                 char buf2[200];
00509                 sprintf(buf,"%s/logs/%ld",packagePath.c_str(),currentLogID);
00510                 sprintf(buf2,"%s/logs/%ld-%lds",packagePath.c_str(),currentLogID,(getMS()-startedLogClock+500)/1000);
00511                 rename(buf,buf2);
00512         }
00513 
00514 }
00515 
00516 void EstimationNode::reSendInfo()
00517 {
00518 
00519         // get ptam status string
00520         std::string ptamStatus;
00521         switch(ptamWrapper->PTAMStatus)
00522         {
00523         case PTAMWrapper::PTAM_IDLE:
00524                 ptamStatus = "Idle";
00525                 break;
00526         case PTAMWrapper::PTAM_INITIALIZING:
00527                 ptamStatus = "Initializing";
00528                 break;
00529         case PTAMWrapper::PTAM_LOST:
00530                 ptamStatus = "Lost";
00531                 break;
00532         case PTAMWrapper::PTAM_FALSEPOSITIVE:
00533                 ptamStatus = "FalsePositive";
00534                 break;
00535         case PTAMWrapper::PTAM_GOOD:
00536                 ptamStatus = "Good";
00537                 break;
00538         case PTAMWrapper::PTAM_TOOKKF:
00539         case PTAMWrapper::PTAM_BEST:
00540                 ptamStatus = "Best";
00541                 break;
00542         }
00543 
00544 
00545 
00546         // parse PTAM message
00547         std::string ptamMsg = ptamWrapper->lastPTAMMessage;
00548         int kf, kp, kps[4], kpf[4];
00549         size_t pos = ptamMsg.find("Found: ");
00550         int found = 0;
00551         if(pos != std::string::npos)
00552                 found = sscanf(ptamMsg.substr(pos).c_str(),"Found: %d/%d %d/%d %d/%d %d/%d Map: %dP, %dKF",
00553                                                 &kpf[0],&kps[0],&kpf[1],&kps[1],&kpf[2],&kps[2],&kpf[3],&kps[3],&kp,&kf);
00554         char bufp[200];
00555         if(found == 10)
00556                 snprintf(bufp,200,"Map: KF: %d, KP: %d (%d of %d found)",
00557                                 kf, kp,kpf[0]+kpf[1]+kpf[2]+kpf[3], kps[0]+kps[1]+kps[2]+kps[3]);
00558         else
00559                 snprintf(bufp,200,"Map: -");
00560 
00561         std::string status = "";
00562         switch( lastNavdataReceived.state)
00563         {
00564                 case 0: status = "Unknown";break;
00565                 case 1: status = "Init"; break;
00566                 case 2: status = "Landed";break;
00567                 case 3: status = "Flying"; break;
00568                 case 4: status = "Hovering";break;
00569                 case 5: status = "Test"; break;
00570                 case 6: status = "Taking off";break;
00571                 case 7: status = "Goto Fix Point"; break;
00572                 case 8: status = "Landing";break;
00573                 case 9: status = "Looping"; break;
00574         }
00575         /*
00576         PTAM: Idle | Good | Dodgy | Lost
00577         Map: KF: X, KP: X (X searched, X found)
00578         Scale: X (in: X, out: x), acc: X
00579         Scale Fixpoint: NONE | DRONE
00580         Status: X (Battery: X)
00581         */
00582         char buf[1000];
00583         snprintf(buf,1000,"u s PTAM: %s\n%s\nScale: %.3f (%d in, %d out), acc: %.2f\nScaleFixpoint: %s\nDrone Status: %s (%d Battery)",
00584                         ptamStatus.c_str(),
00585                         bufp,
00586                         filter->getCurrentScales()[0],filter->scalePairsIn,filter->scalePairsOut,filter->getScaleAccuracy(),
00587                         filter->useScalingFixpoint ? "FIX" : "DRONE",
00588                         status.c_str(), (int)lastNavdataReceived.batteryPercent);
00589 
00590         publishCommand(buf);
00591 }


uga_tum_ardrone
Author(s):
autogenerated on Sat Jun 8 2019 20:30:11