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
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
00072 logfileControl = 0;
00073 hoverCommand.gaz = hoverCommand.pitch = hoverCommand.roll = hoverCommand.yaw = 0;
00074 lastControlSentMS = 0;
00075
00076
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
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
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
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
00121 pthread_mutex_lock(&commandQueue_CS);
00122
00123
00124
00125 while(currentKI == NULL && commandQueue.size() > 0)
00126 popNextCommand(statePtr);
00127
00128
00129 if(currentKI != NULL)
00130 {
00131
00132 this->updateControl(statePtr);
00133 }
00134 else if(isControlling)
00135 {
00136 sendControlToDrone(controller.update(statePtr));
00137
00138
00139 }
00140
00141
00142 pthread_mutex_unlock(&commandQueue_CS);
00143 }
00144
00145
00146
00147 void ControlNode::popNextCommand(const uga_tum_ardrone::filter_stateConstPtr statePtr)
00148 {
00149
00150
00151 if(currentKI != NULL)
00152 {
00153 delete currentKI;
00154 currentKI = NULL;
00155 }
00156
00157
00158 while(currentKI == NULL && commandQueue.size() > 0)
00159 {
00160 std::string command = commandQueue.front();
00161 commandQueue.pop_front();
00162 bool commandUnderstood = false;
00163
00164
00165 ROS_INFO("executing command: %s",command.c_str());
00166
00167 int p;
00168 char buf[100];
00169 float parameters[10];
00170
00171
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
00184
00185 if(sscanf(command.c_str(),"autoInit %f %f %f %f",¶meters[0], ¶meters[1], ¶meters[2], ¶meters[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",¶meters[0], ¶meters[1], ¶meters[2], ¶meters[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
00200 else if(command == "takeoff")
00201 {
00202 currentKI = new KIAutoInit(false);
00203 currentKI->setPointers(this,&controller);
00204 commandUnderstood = true;
00205 }
00206
00207
00208 else if(sscanf(command.c_str(),"setReference %f %f %f %f",¶meters[0], ¶meters[1], ¶meters[2], ¶meters[3]) == 4)
00209 {
00210 parameter_referenceZero = DronePosition(TooN::makeVector(parameters[0],parameters[1],parameters[2]),parameters[3]);
00211 commandUnderstood = true;
00212 }
00213
00214
00215 else if(sscanf(command.c_str(),"setMaxControl %f",¶meters[0]) == 1)
00216 {
00217 parameter_MaxControl = parameters[0];
00218 commandUnderstood = true;
00219 }
00220
00221
00222 else if(sscanf(command.c_str(),"setInitialReachDist %f",¶meters[0]) == 1)
00223 {
00224 parameter_InitialReachDist = parameters[0];
00225 commandUnderstood = true;
00226 }
00227
00228
00229 else if(sscanf(command.c_str(),"setStayWithinDist %f",¶meters[0]) == 1)
00230 {
00231 parameter_StayWithinDist = parameters[0];
00232 commandUnderstood = true;
00233 }
00234
00235
00236 else if(sscanf(command.c_str(),"setStayTime %f",¶meters[0]) == 1)
00237 {
00238 parameter_StayTime = parameters[0];
00239 commandUnderstood = true;
00240 }
00241
00242
00243 else if(sscanf(command.c_str(),"goto %f %f %f %f",¶meters[0], ¶meters[1], ¶meters[2], ¶meters[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
00260 else if(sscanf(command.c_str(),"moveBy %f %f %f %f",¶meters[0], ¶meters[1], ¶meters[2], ¶meters[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
00277 else if(sscanf(command.c_str(),"moveByRel %f %f %f %f",¶meters[0], ¶meters[1], ¶meters[2], ¶meters[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
00294 else if(command == "land")
00295 {
00296 currentKI = new KILand();
00297 currentKI->setPointers(this,&controller);
00298 commandUnderstood = true;
00299 }
00300
00301
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
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
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
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
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
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
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);
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
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
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
00498
00499
00500
00501
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
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();
00542 controller.clearTarget();
00543 if(currentKI != NULL) delete currentKI;
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