ControlNode.cpp
Go to the documentation of this file.
00001 
00024 #include "ControlNode.h"
00025 #include "ros/ros.h"
00026 #include "ros/callback_queue.h"
00027 #include <ros/package.h>
00028 
00029 #include "geometry_msgs/Twist.h"
00030 #include "../HelperFunctions.h"
00031 #include "uga_tum_ardrone/filter_state.h"
00032 #include "std_msgs/String.h"
00033 #include <sys/stat.h>
00034 #include <string>
00035 
00036 // include KI's
00037 #include "KI/KIAutoInit.h"
00038 #include "KI/KIFlyTo.h"
00039 #include "KI/KILand.h"
00040 #include "KI/KIProcedure.h"
00041 
00042 using namespace uga_tum_ardrone;
00043 using namespace std;
00044 
00045 pthread_mutex_t ControlNode::logControl_CS = PTHREAD_MUTEX_INITIALIZER;
00046 
00047 
00048 ControlNode::ControlNode()
00049 {
00050     control_channel = nh_.resolveName("cmd_vel");
00051     dronepose_channel = nh_.resolveName("ardrone/predictedPose");
00052     command_channel = nh_.resolveName("uga_tum_ardrone/com");
00053     takeoff_channel = nh_.resolveName("ardrone/takeoff");
00054     land_channel = nh_.resolveName("ardrone/land");
00055     toggleState_channel = nh_.resolveName("ardrone/reset");
00056 
00057         packagePath = ros::package::getPath("uga_tum_ardrone");
00058 
00059         std::string val;
00060         float valFloat;
00061 
00062         ros::param::get("~minPublishFreq", val);
00063         if(val.size()>0)
00064                 sscanf(val.c_str(), "%f", &valFloat);
00065         else
00066                 valFloat = 110;
00067         minPublishFreq = valFloat;
00068         cout << "set minPublishFreq to " << valFloat << "ms"<< endl;
00069 
00070 
00071         // other internal vars
00072         logfileControl = 0;
00073         hoverCommand.gaz = hoverCommand.pitch = hoverCommand.roll = hoverCommand.yaw = 0;
00074         lastControlSentMS = 0;
00075 
00076         // channels
00077         dronepose_sub = nh_.subscribe(dronepose_channel, 10, &ControlNode::droneposeCb, this);
00078         vel_pub    = nh_.advertise<geometry_msgs::Twist>(control_channel,1);
00079         uga_tum_ardrone_pub        = nh_.advertise<std_msgs::String>(command_channel,50);
00080         uga_tum_ardrone_sub        = nh_.subscribe(command_channel,50, &ControlNode::comCb, this);
00081         takeoff_pub        = nh_.advertise<std_msgs::Empty>(takeoff_channel,1);
00082         land_pub           = nh_.advertise<std_msgs::Empty>(land_channel,1);
00083         toggleState_pub    = nh_.advertise<std_msgs::Empty>(toggleState_channel,1);
00084 
00085         // services handler
00086         setReference_ = nh_.advertiseService("drone_autopilot/setReference", &ControlNode::setReference, this);
00087         setMaxControl_ = nh_.advertiseService("drone_autopilot/setMaxControl", &ControlNode::setMaxControl, this);
00088         setInitialReachDistance_ = nh_.advertiseService("drone_autopilot/setInitialReachDistance", &ControlNode::setInitialReachDistance, this);
00089         setStayWithinDistance_ = nh_.advertiseService("drone_autopilot/setStayWithinDistance", &ControlNode::setStayWithinDistance, this);
00090         setStayTime_ = nh_.advertiseService("drone_autopilot/setStayTime", &ControlNode::setStayTime, this);
00091         startControl_ = nh_.advertiseService("drone_autopilot/start", &ControlNode::start, this);
00092         stopControl_ = nh_.advertiseService("drone_autopilot/stop", &ControlNode::stop, this);
00093         clearCommands_ = nh_.advertiseService("drone_autopilot/clearCommands", &ControlNode::clear, this);
00094         hover_ = nh_.advertiseService("drone_autopilot/hover", &ControlNode::hover, this);
00095         lockScaleFP_ = nh_.advertiseService("drone_autopilot/lockScaleFP", &ControlNode::lockScaleFP, this);
00096 
00097         // internals
00098         parameter_referenceZero = DronePosition(TooN::makeVector(0,0,0),0);
00099         parameter_MaxControl = 1;
00100         parameter_InitialReachDist = 0.2;
00101         parameter_StayWithinDist = 0.5;
00102         parameter_StayTime = 2;
00103         isControlling = false;
00104         currentKI = NULL;
00105         lastSentControl = ControlCommand(0,0,0,0);
00106 
00107         // create controller
00108         controller = DroneController();
00109         controller.node = this;
00110 }
00111 
00112 ControlNode::~ControlNode()
00113 {
00114 
00115 }
00116 
00117 pthread_mutex_t ControlNode::commandQueue_CS = PTHREAD_MUTEX_INITIALIZER;
00118 void ControlNode::droneposeCb(const uga_tum_ardrone::filter_stateConstPtr statePtr)
00119 {
00120         // do controlling
00121         pthread_mutex_lock(&commandQueue_CS);
00122 
00123         // as long as no KI present:
00124         // pop next KI (if next KI present).
00125         while(currentKI == NULL && commandQueue.size() > 0)
00126                 popNextCommand(statePtr);
00127 
00128         // if there is no current KI now, we obviously have no current goal -> send drone hover
00129         if(currentKI != NULL)
00130         {
00131                 // let current KI control.
00132                 this->updateControl(statePtr);
00133         }
00134         else if(isControlling)
00135         {
00136             sendControlToDrone(controller.update(statePtr));
00137 //              sendControlToDrone(hoverCommand);
00138 //              ROS_DEBUG("Autopilot is Controlling, but there is no KI -> sending HOVER");
00139         }
00140 
00141 
00142         pthread_mutex_unlock(&commandQueue_CS);
00143 }
00144 
00145 // pops next command(s) from queue (until one is found thats not "done" yet).
00146 // assumes propery of command queue lock exists (!)
00147 void ControlNode::popNextCommand(const uga_tum_ardrone::filter_stateConstPtr statePtr)
00148 {
00149         // should actually not happen., but to make shure:
00150         // delete existing KI.
00151         if(currentKI != NULL)
00152         {
00153                 delete currentKI;
00154                 currentKI = NULL;
00155         }
00156 
00157         // read next command.
00158         while(currentKI == NULL && commandQueue.size() > 0)
00159         {
00160                 std::string command = commandQueue.front();
00161                 commandQueue.pop_front();
00162                 bool commandUnderstood = false;
00163 
00164                 // print me
00165                 ROS_INFO("executing command: %s",command.c_str());
00166 
00167                 int p;
00168                 char buf[100];
00169                 float parameters[10];
00170 
00171                 // replace macros
00172                 if((p = command.find("$POSE$")) != std::string::npos)
00173                 {
00174                         snprintf(buf,100, "%.3f %.3f %.3f %.3f",statePtr->x,statePtr->y,statePtr->z,statePtr->yaw);
00175                         command.replace(p,6,buf);
00176                 }
00177                 if((p = command.find("$REFERENCE$")) != std::string::npos)
00178                 {
00179                         snprintf(buf,100, "%.3f %.3f %.3f %.3f",parameter_referenceZero.pos[0],parameter_referenceZero.pos[1],parameter_referenceZero.pos[2],parameter_referenceZero.yaw);
00180                         command.replace(p,11,buf);
00181                 }
00182 
00183                 // -------- commands -----------
00184                 // autoInit
00185                 if(sscanf(command.c_str(),"autoInit %f %f %f %f",&parameters[0], &parameters[1], &parameters[2], &parameters[3]) == 4)
00186                 {
00187                         currentKI = new KIAutoInit(true,parameters[0],parameters[1],parameters[2],parameters[3],true);
00188                         currentKI->setPointers(this,&controller);
00189                         commandUnderstood = true;
00190                 }
00191 
00192                 else if(sscanf(command.c_str(),"autoTakeover %f %f %f %f",&parameters[0], &parameters[1], &parameters[2], &parameters[3]) == 4)
00193                 {
00194                         currentKI = new KIAutoInit(true,parameters[0],parameters[1],parameters[2],parameters[3],false);
00195                         currentKI->setPointers(this,&controller);
00196                         commandUnderstood = true;
00197                 }
00198 
00199                 // takeoff
00200                 else if(command == "takeoff")
00201                 {
00202                         currentKI = new KIAutoInit(false);
00203                         currentKI->setPointers(this,&controller);
00204                         commandUnderstood = true;
00205                 }
00206 
00207                 // setOffset
00208                 else if(sscanf(command.c_str(),"setReference %f %f %f %f",&parameters[0], &parameters[1], &parameters[2], &parameters[3]) == 4)
00209                 {
00210                         parameter_referenceZero = DronePosition(TooN::makeVector(parameters[0],parameters[1],parameters[2]),parameters[3]);
00211                         commandUnderstood = true;
00212                 }
00213 
00214                 // setMaxControl
00215                 else if(sscanf(command.c_str(),"setMaxControl %f",&parameters[0]) == 1)
00216                 {
00217                         parameter_MaxControl = parameters[0];
00218                         commandUnderstood = true;
00219                 }
00220 
00221                 // setInitialReachDist
00222                 else if(sscanf(command.c_str(),"setInitialReachDist %f",&parameters[0]) == 1)
00223                 {
00224                         parameter_InitialReachDist = parameters[0];
00225                         commandUnderstood = true;
00226                 }
00227 
00228                 // setStayWithinDist
00229                 else if(sscanf(command.c_str(),"setStayWithinDist %f",&parameters[0]) == 1)
00230                 {
00231                         parameter_StayWithinDist = parameters[0];
00232                         commandUnderstood = true;
00233                 }
00234 
00235                 // setStayTime
00236                 else if(sscanf(command.c_str(),"setStayTime %f",&parameters[0]) == 1)
00237                 {
00238                         parameter_StayTime = parameters[0];
00239                         commandUnderstood = true;
00240                 }
00241 
00242                 // goto
00243                 else if(sscanf(command.c_str(),"goto %f %f %f %f",&parameters[0], &parameters[1], &parameters[2], &parameters[3]) == 4)
00244                 {
00245                         currentKI = new KIFlyTo(
00246                                 DronePosition(
00247                                 TooN::makeVector(parameters[0],parameters[1],parameters[2]) + parameter_referenceZero.pos,
00248                                         parameters[3] + parameter_referenceZero.yaw),
00249                                 parameter_StayTime,
00250                                 parameter_MaxControl,
00251                                 parameter_InitialReachDist,
00252                                 parameter_StayWithinDist
00253                                 );
00254                         currentKI->setPointers(this,&controller);
00255                         commandUnderstood = true;
00256 
00257                 }
00258 
00259                 // moveBy
00260                 else if(sscanf(command.c_str(),"moveBy %f %f %f %f",&parameters[0], &parameters[1], &parameters[2], &parameters[3]) == 4)
00261                 {
00262                         currentKI = new KIFlyTo(
00263                                 DronePosition(
00264                                 TooN::makeVector(parameters[0],parameters[1],parameters[2]) + controller.getCurrentTarget().pos,
00265                                         parameters[3] + controller.getCurrentTarget().yaw),
00266                                 parameter_StayTime,
00267                                 parameter_MaxControl,
00268                                 parameter_InitialReachDist,
00269                                 parameter_StayWithinDist
00270                                 );
00271                         currentKI->setPointers(this,&controller);
00272                         commandUnderstood = true;
00273 
00274                 }
00275 
00276                 // moveByRel
00277                 else if(sscanf(command.c_str(),"moveByRel %f %f %f %f",&parameters[0], &parameters[1], &parameters[2], &parameters[3]) == 4)
00278                 {
00279                         currentKI = new KIFlyTo(
00280                                 DronePosition(
00281                                 TooN::makeVector(parameters[0]+statePtr->x,parameters[1]+statePtr->y,parameters[2]+statePtr->z),
00282                                         parameters[3] + statePtr->yaw),
00283                                 parameter_StayTime,
00284                                 parameter_MaxControl,
00285                                 parameter_InitialReachDist,
00286                                 parameter_StayWithinDist
00287                                 );
00288                         currentKI->setPointers(this,&controller);
00289                         commandUnderstood = true;
00290 
00291                 }
00292 
00293                 // land
00294                 else if(command == "land")
00295                 {
00296                         currentKI = new KILand();
00297                         currentKI->setPointers(this,&controller);
00298                         commandUnderstood = true;
00299                 }
00300 
00301                 // setScaleFP
00302                 else if(command == "lockScaleFP")
00303                 {
00304                         publishCommand("p lockScaleFP");
00305                         commandUnderstood = true;
00306                 }
00307 
00308                 if(!commandUnderstood)
00309                         ROS_INFO("unknown command, skipping!");
00310         }
00311 
00312 }
00313 
00314 void ControlNode::comCb(const std_msgs::StringConstPtr str)
00315 {
00316         // only handle commands with prefix c
00317         if(str->data.length() > 2 && str->data.substr(0,2) == "c ")
00318         {
00319                 std::string cmd =str->data.substr(2,str->data.length()-2);
00320 
00321                 if(cmd.length() == 4 && cmd.substr(0,4) == "stop")
00322                 {
00323                         stopControl();
00324                 }
00325                 else if(cmd.length() == 5 && cmd.substr(0,5) == "start")
00326                 {
00327                         startControl();
00328                 }
00329                 else if(cmd.length() == 13 && cmd.substr(0,13) == "clearCommands")
00330                 {
00331                         clearCommands();
00332                 }
00333                 else
00334                 {
00335                         pthread_mutex_lock(&commandQueue_CS);
00336                         commandQueue.push_back(cmd);
00337                         pthread_mutex_unlock(&commandQueue_CS);
00338                 }
00339         }
00340 
00341         // global command: toggle log
00342         if(str->data.length() == 9 && str->data.substr(0,9) == "toggleLog")
00343         {
00344                 this->toogleLogging();
00345         }
00346 }
00347 
00348 void ControlNode::Loop()
00349 {
00350         ros::Time last = ros::Time::now();
00351         ros::Time lastStateUpdate = ros::Time::now();
00352 
00353         while (nh_.ok())
00354         {
00355 
00356                 // -------------- 1. spin for 50ms, do main controlling part here. ---------------
00357                 while((ros::Time::now() - last) < ros::Duration(minPublishFreq / 1000.0))
00358                         ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(minPublishFreq / 1000.0 - (ros::Time::now() - last).toSec()));
00359                 last = ros::Time::now();
00360 
00361 
00362                 // -------------- 2. send hover (maybe). ---------------
00363                 if(isControlling && getMS(ros::Time::now()) - lastControlSentMS > minPublishFreq)
00364                 {
00365                         sendControlToDrone(hoverCommand);
00366                         ROS_WARN("Autopilot enabled, but no estimated pose received - sending HOVER.");
00367                 }
00368 
00369                 // -------------- 2. update info. ---------------
00370                 if((ros::Time::now() - lastStateUpdate) > ros::Duration(0.4))
00371                 {
00372                         reSendInfo();
00373                         lastStateUpdate = ros::Time::now();
00374                 }
00375         }
00376 }
00377 void ControlNode::dynConfCb(uga_tum_ardrone::AutopilotParamsConfig &config, uint32_t level)
00378 {
00379         controller.K_direct = config.K_direct;
00380         controller.K_rp = config.K_rp;
00381         controller.droneMassInKilos = config.droneMassInKilos;
00382         controller.max_rp_radians = config.max_rp_radians;
00383 
00384         controller.max_gaz_drop = config.max_gaz_drop;
00385         controller.max_gaz_rise = config.max_gaz_rise;
00386         controller.max_rp = config.max_rp;
00387         controller.max_yaw = config.max_yaw;
00388         controller.agressiveness = config.agressiveness;
00389         controller.rise_fac = config.rise_fac;
00390     controller.xy_damping_factor = config.xy_damping_factor;
00391 
00392 }
00393 
00394 pthread_mutex_t ControlNode::uga_tum_ardrone_CS = PTHREAD_MUTEX_INITIALIZER;
00395 void ControlNode::publishCommand(std::string c)
00396 {
00397         std_msgs::String s;
00398         s.data = c.c_str();
00399         pthread_mutex_lock(&uga_tum_ardrone_CS);
00400         uga_tum_ardrone_pub.publish(s);
00401         pthread_mutex_unlock(&uga_tum_ardrone_CS);
00402 }
00403 
00404 
00405 void ControlNode::toogleLogging()
00406 {
00407         // first: always check for /log dir
00408         struct stat st;
00409         if(stat((packagePath+std::string("/logs")).c_str(),&st) != 0)
00410                 mkdir((packagePath+std::string("/logs")).c_str(),S_IXGRP | S_IXOTH | S_IXUSR | S_IRWXU | S_IRWXG | S_IROTH);
00411 
00412         char buf[200];
00413         bool quitLogging = false;
00414         if(logfileControl == 0)
00415         {
00416                 currentLogID = ((long)time(0))*100+(getMS()%100);               // time(0) + ms
00417                 startedLogClock = getMS();
00418                 ROS_INFO("\n\nENABLED LOGGING to %s/logs/%ld\n\n\n",packagePath.c_str(),currentLogID);
00419                 sprintf(buf,"%s/logs/%ld",packagePath.c_str(),currentLogID);
00420                 mkdir(buf, S_IXGRP | S_IXOTH | S_IXUSR | S_IRWXU | S_IRWXG | S_IROTH);
00421 
00422 
00423                 sprintf(buf,"u l ENABLED LOGGING to %s/logs/%ld",packagePath.c_str(),currentLogID);
00424                 publishCommand(buf);
00425         }
00426         else
00427                 quitLogging = true;
00428 
00429 
00430 
00431         // IMU
00432         pthread_mutex_lock(&logControl_CS);
00433         if(logfileControl == 0)
00434         {
00435                 logfileControl = new std::ofstream();
00436                 sprintf(buf,"%s/logs/%ld/logControl.txt",packagePath.c_str(),currentLogID);
00437                 logfileControl->open (buf);
00438         }
00439         else
00440         {
00441                 logfileControl->flush();
00442                 logfileControl->close();
00443                 delete logfileControl;
00444                 logfileControl = NULL;
00445         }
00446         pthread_mutex_unlock(&logControl_CS);
00447 
00448 
00449         if(quitLogging)
00450         {
00451                 printf("\n\nDISABLED LOGGING (logged %ld sec)\n\n\n",(getMS()-startedLogClock+500)/1000);
00452                 char buf2[200];
00453                 sprintf(buf,"%s/logs/%ld",packagePath.c_str(),currentLogID);
00454                 sprintf(buf2,"%s/logs/%ld-%lds",packagePath.c_str(),currentLogID,(getMS()-startedLogClock+500)/1000);
00455                 rename(buf,buf2);
00456         }
00457 }
00458 
00459 void ControlNode::sendControlToDrone(ControlCommand cmd)
00460 {
00461         geometry_msgs::Twist cmdT;
00462         cmdT.angular.z = -cmd.yaw;
00463         cmdT.linear.z = cmd.gaz;
00464         cmdT.linear.x = -cmd.pitch;
00465         cmdT.linear.y = -cmd.roll;
00466 
00467         // assume that while actively controlling, the above for will never be equal to zero, so i will never hover.
00468         cmdT.angular.x = cmdT.angular.y = 0;
00469 
00470         if(isControlling)
00471         {
00472                 vel_pub.publish(cmdT);
00473                 lastSentControl = cmd;
00474         }
00475 
00476         lastControlSentMS = getMS(ros::Time::now());
00477 }
00478 
00479 void ControlNode::sendLand()
00480 {
00481         if(isControlling)
00482                 land_pub.publish(std_msgs::Empty());
00483 }
00484 void ControlNode::sendTakeoff()
00485 {
00486         if(isControlling)
00487                 takeoff_pub.publish(std_msgs::Empty());
00488 }
00489 void ControlNode::sendToggleState()
00490 {
00491         if(isControlling)
00492                 toggleState_pub.publish(std_msgs::Empty());
00493 }
00494 void ControlNode::reSendInfo()
00495 {
00496         /*
00497         Idle / Controlling (Queue: X)
00498         Current:
00499         Next:
00500         Target: X,X,X,X
00501         Error: X,X,X,X
00502         */
00503 
00504         DronePosition p = controller.getCurrentTarget();
00505         TooN::Vector<4> e = controller.getLastErr();
00506         double ea = sqrt(e[0]*e[0] + e[1]*e[1] + e[2]*e[2]);
00507         snprintf(buf,500,"u c %s (Queue: %d)\nCurrent: %s\nNext: %s\nTarget: (%.2f,  %.2f,  %.2f), %.1f\nError: (%.2f,  %.2f,  %.2f), %.1f (|.| %.2f)\nCont.: r %.2f, p %.2f, g %.2f, y %.2f",
00508                         isControlling ? "Controlling" : "Idle",
00509                         (int)commandQueue.size(),
00510                         currentKI == NULL ? "NULL" : currentKI->command.c_str(),
00511                         commandQueue.size() > 0 ? commandQueue.front().c_str() : "NULL",
00512                         p.pos[0],p.pos[1],p.pos[2],p.yaw,
00513                         e[0],e[1],e[2],e[3], ea,
00514                         lastSentControl.roll, lastSentControl.pitch, lastSentControl.gaz, lastSentControl.yaw);
00515 
00516         publishCommand(buf);
00517 }
00518 
00519 void ControlNode::startControl() {
00520         isControlling = true;
00521         publishCommand("u l Autopilot: Start Controlling");
00522         ROS_INFO("START CONTROLLING!");
00523 }
00524 
00525 void ControlNode::stopControl() {
00526         isControlling = false;
00527         publishCommand("u l Autopilot: Stop Controlling");
00528         ROS_INFO("STOP CONTROLLING!");
00529 }
00530 
00531 void ControlNode::updateControl(const uga_tum_ardrone::filter_stateConstPtr statePtr) {
00532 //      if (currentKI->update(statePtr) && commandQueue.size() > 0) {
00533         if (currentKI->update(statePtr)) {
00534                 delete currentKI;
00535                 currentKI = NULL;
00536         }
00537 }
00538 
00539 void ControlNode::clearCommands() {
00540         pthread_mutex_lock(&commandQueue_CS);
00541         commandQueue.clear();                                           // clear command queue.
00542         controller.clearTarget();                                       // clear current controller target
00543         if(currentKI != NULL) delete currentKI; // destroy & delete KI.
00544         currentKI = NULL;
00545         pthread_mutex_unlock(&commandQueue_CS);
00546         publishCommand("u l Autopilot: Cleared Command Queue");
00547         ROS_INFO("Cleared Command Queue!");
00548 }
00549 
00550 bool ControlNode::setReference(SetReference::Request& req, SetReference::Response& res)
00551 {
00552         ROS_INFO("calling service setReference");
00553         parameter_referenceZero = DronePosition(TooN::makeVector(req.x, req.y, req.z), req.heading);
00554         res.status = true;
00555         return true;
00556 }
00557 
00558 bool ControlNode::setMaxControl(SetMaxControl::Request& req, SetMaxControl::Response& res)
00559 {
00560         ROS_INFO("calling service setMaxControl");
00561         parameter_MaxControl = req.speed;
00562         res.status = true;
00563         return true;
00564 }
00565 
00566 bool ControlNode::setInitialReachDistance(SetInitialReachDistance::Request& req, SetInitialReachDistance::Response& res)
00567 {
00568         ROS_INFO("calling service setInitialReachDistance");
00569         parameter_InitialReachDist = req.distance;
00570         res.status = true;
00571         return true;
00572 }
00573 
00574 bool ControlNode::setStayWithinDistance(SetStayWithinDistance::Request& req, SetStayWithinDistance::Response& res) {
00575         ROS_INFO("calling service setStayWithinDistance");
00576         parameter_StayWithinDist = req.distance;
00577         res.status = true;
00578         return true;
00579 }
00580 
00581 bool ControlNode::setStayTime(SetStayTime::Request& req, SetStayTime::Response& res) {
00582         ROS_INFO("calling service setStayTime");
00583         parameter_StayTime = req.duration;
00584         res.status = true;
00585         return true;
00586 }
00587 
00588 bool ControlNode::start(std_srvs::Empty::Request& req, std_srvs::Empty::Response& res) {
00589         ROS_INFO("calling service start");
00590         this->startControl();
00591         return true;
00592 }
00593 
00594 bool ControlNode::stop(std_srvs::Empty::Request&, std_srvs::Empty::Response&) {
00595         ROS_INFO("calling service stop");
00596         this->stopControl();
00597         return true;
00598 }
00599 
00600 bool ControlNode::clear(std_srvs::Empty::Request&, std_srvs::Empty::Response&) {
00601         ROS_INFO("calling service clearCommands");
00602         this->clearCommands();
00603         return true;
00604 }
00605 
00606 bool ControlNode::hover(std_srvs::Empty::Request&, std_srvs::Empty::Response&) {
00607         ROS_INFO("calling service hover");
00608         this->sendControlToDrone(hoverCommand);
00609         return true;
00610 }
00611 
00612 bool ControlNode::lockScaleFP(std_srvs::Empty::Request&, std_srvs::Empty::Response&) {
00613         ROS_INFO("calling service lockScaleFP");
00614         this->publishCommand("p lockScaleFP");
00615         return true;
00616 }
00617 


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