basic_controller_old.cpp
Go to the documentation of this file.
00001 // This is a ROS version of the standard "hello ardrone" program.
00002 
00003 // This header defines the standard ROS classes.
00004 #include <ardrone_autonomy/Navdata.h>
00005 #include <ros/ros.h>
00006 #include <nav_msgs/Odometry.h>
00007 #include <signal.h>
00008 #include "geometry_msgs/Twist.h"
00009 #include "std_msgs/Empty.h"
00010 
00011 double Kp_alt=0.3;
00012 double Ki_alt=0;
00013 double Kd_alt=75;
00014 double Kp_yaw=25;
00015 double Kp_plan=0.6;
00016 double Ki_plan=0;
00017 //double Kd_plan=0.0015; //This Kd is good for y
00018 double Kd_plan=0;
00019 //double Ki_yaw=0.0001;
00020 double Ki_yaw=40;
00021 double Kd_yaw=0;
00022 double integral_alt_error=0;
00023 double integral_yaw_error=0;
00024 double integral_xy_error=0;
00025 double integral_f_error=0;
00026 double integral_l_error=0;
00027 double anti_windup_yaw=0.5;
00028 
00029 double regu_old_time_z;  //How to initialize it?
00030 double regu_old_time_yaw;
00031 double regu_old_time_xy;
00032 double old_delta_alt;
00033 double old_delta_yaw;
00034 double dist_old;
00035 double p_term_f_old;
00036 double p_term_l_old;
00037 double alt_desired_old=0;
00038 double yaw_desired_old=0;
00039 double x_desired_old=0;
00040 double y_desired_old=0;
00041 double last_vel_z_command;
00042 double last_vel_yaw_command;
00043 double last_vel_x_command;
00044 double last_vel_y_command;
00045 double old_yaw_desired=0;
00046 
00047 struct ControlCommand
00048 {
00049   inline ControlCommand()
00050   {
00051     roll = pitch = yaw = gaz = 0;
00052   }
00053   inline ControlCommand(double pitch, double roll, double yaw, double gaz)
00054   {
00055     this->roll = roll;
00056     this->pitch = pitch;
00057     this->yaw = yaw;
00058     this->gaz = gaz;
00059   }
00060   double yaw, roll, pitch, gaz;
00061 };
00062 
00063 ros::Publisher land_pub;
00064 ros::Publisher vel_pub;
00065 // double desired_alt;
00066 bool isControlling = false;
00067 ardrone_autonomy::Navdata lastNavdataReceived;
00068 nav_msgs::Odometry lastOdometryReceived;
00069 
00070 void navdataCb(const ardrone_autonomy::Navdata::ConstPtr navdataPtr)
00071 {
00072   lastNavdataReceived = *navdataPtr;
00073   // ROS_INFO("altd: %i", lastNavdataReceived.altd);
00074 }
00075 
00076 void odometryCb(const nav_msgs::Odometry::ConstPtr odometryPtr)
00077 {
00078   lastOdometryReceived = *odometryPtr;
00079 }
00080 
00081 void basic_sigint_handler(int sig)
00082 {
00083   geometry_msgs::Twist cmdT;
00084   cmdT.angular.z = 0;
00085   cmdT.linear.z = 0;
00086   cmdT.linear.x = 0;
00087   cmdT.linear.y = 0;
00088 
00089   // assume that while actively controlling, the above for will never be equal to zero, so i will never hover.
00090   cmdT.angular.x = cmdT.angular.y = 0;
00091 
00092 
00093     vel_pub.publish(cmdT);
00094     // lastSentControl = cmd;
00095 
00096   land_pub.publish(std_msgs::Empty());
00097   ros::shutdown();
00098 }
00099 
00100 // Altitude controller
00101 void path_regu_altitude(double *zvel_cmd, double alt_mes, double alt_desired, double regu_new_time_z)
00102 {
00103   double p_term;
00104   double d_term=0; //In case time_diff = 0
00105   double i_term;
00106 
00107   double time_difference=(regu_new_time_z-regu_old_time_z)/1000;
00108 
00109   //If navdata has the same timestamp, send the last command
00110   if(time_difference!=0){
00111   //printf("time_difference: %lf, regu_old_time: %lf, regu_new_time/ %lf \n", time_difference, regu_old_time, regu_new_time);
00112     if(alt_desired_old!=alt_desired){
00113         integral_alt_error=0;
00114     }
00115     alt_desired_old=alt_desired;
00116     regu_old_time_z=regu_new_time_z;
00117     double delta_alt=-alt_mes+alt_desired;
00118     p_term=delta_alt;  //Checker le signe!
00119     if(time_difference!=0){
00120         //printf("Entering if. delta_alt: %lf, old_delta_alt: %lf:", delta_alt, old_delta_alt);
00121         d_term=(delta_alt-old_delta_alt)/time_difference;
00122         old_delta_alt=delta_alt;
00123     }
00124     integral_alt_error+=delta_alt*time_difference;
00125     i_term=integral_alt_error;
00126 
00127     last_vel_z_command=(Kp_alt*p_term+i_term*Ki_alt+Kd_alt*d_term)/10;
00128     *zvel_cmd=last_vel_z_command;
00129     //printf("zvel_cmd: %lf \n", last_vel_z_command);
00130   /*printf("p_term: %lf\n",p_term);
00131   printf("d_term: %lf\n",d_term);
00132   printf("i_term: %lf\n",i_term);*/
00133     }
00134   else{
00135     *zvel_cmd=last_vel_z_command;
00136   }
00137 }
00138 
00139   void path_regu_yaw(double *yawvel_cmd, double yaw_mes, double yaw_desired, double regu_new_time)
00140  {
00141 
00142     //ROS_INFO_STREAM("Regulating");
00143   double p_term;
00144   double d_term=0; //In case time_diff = 0
00145   double i_term;
00146 
00147   double time_difference=(regu_new_time-regu_old_time_yaw)/1000; //On obtient un nombre de millier de secondes... A changer!
00148   double new_vel_yaw_cmd;
00149 
00150   //If navdata has the same timestamp, send the last command
00151   if(time_difference!=0){
00152   //printf("time_difference: %lf, regu_old_time_yaw: %lf, regu_new_time/ %lf \n", time_difference, regu_old_time_yaw, regu_new_time);
00153   if(yaw_desired_old!=yaw_desired)
00154   {
00155     integral_yaw_error=0;
00156   }
00157   yaw_desired_old=yaw_desired;
00158   regu_old_time_yaw=regu_new_time;
00159   double delta_yaw=-yaw_mes+yaw_desired;
00160   p_term=delta_yaw;  //Checker le signe!
00161   if(time_difference!=0)
00162   {
00163     //printf("Entering if. delta_alt: %lf, old_delta_alt: %lf:", delta_yaw, old_delta_yaw);
00164     d_term=(delta_yaw-old_delta_yaw)/time_difference;
00165     old_delta_yaw=delta_yaw;
00166   }
00167   integral_yaw_error+=delta_yaw*time_difference;
00168   i_term=integral_yaw_error;
00169   new_vel_yaw_cmd=(Kp_yaw*p_term+i_term*Ki_yaw+Kd_yaw*d_term)/10;
00170   //printf("p_term: %lf, i_term: %lf \n",p_term, i_term);
00171 
00172   //Anti windup
00173   if(new_vel_yaw_cmd>anti_windup_yaw){
00174     new_vel_yaw_cmd=anti_windup_yaw;
00175   }
00176   else if(new_vel_yaw_cmd<-anti_windup_yaw){
00177     new_vel_yaw_cmd=-anti_windup_yaw;
00178   }
00179   last_vel_yaw_command=new_vel_yaw_cmd;
00180   *yawvel_cmd=last_vel_yaw_command;
00181   //printf("yaw_vel_cmd: %lf \n", last_vel_yaw_command);
00182   /*printf("p_term: %lf\n",p_term);
00183   printf("d_term: %lf\n",d_term);
00184   printf("i_term: %lf\n",i_term);*/
00185   }
00186   else{
00187   *yawvel_cmd=last_vel_yaw_command;
00188   }
00189  }
00190 
00191 
00192 
00193  void path_regu_xy(double *xvel_cmd, double *yvel_cmd, double x_mes, double y_mes, double x_desired,double y_desired, double yaw,double regu_new_time_xy)
00194  {
00195   double p_term_l;
00196   double d_term_l=0; //In case time_diff = 0
00197   double i_term_l;
00198   double p_term_f;
00199   double d_term_f=0; //In case time_diff = 0
00200   double i_term_f;
00201 
00202   double time_difference=(regu_new_time_xy-regu_old_time_xy)/1000;
00203 
00204   //If navdata has the same timestamp, send the last command
00205   if(time_difference!=0){
00206     if(x_desired_old!=x_desired||y_desired_old!=y_desired){
00207         integral_xy_error=0;
00208     }
00209     //printf("x: %lf   y: %lf   yaw: %lf\n",x_mes,y_mes,yaw);
00210     double dist=sqrt(pow((x_mes-x_desired),2)+pow((y_mes-y_desired),2));
00211     dist_old=dist;
00212     double delta_x=-x_mes+x_desired;
00213     double delta_y=y_desired-y_mes;
00214     regu_old_time_xy=regu_new_time_xy;
00215     //p_term=dist;  //Checker le signe!
00216     //Could technically be deleted
00217     double c_theta=cos(yaw*3.14159);
00218     double s_theta=sin(yaw*3.14159);
00219     p_term_f=delta_x*c_theta-delta_y*s_theta;
00220     p_term_l=delta_x*s_theta+delta_y*c_theta;
00221 
00222     if(time_difference!=0){
00223         //printf("Entering if. delta_alt: %lf, old_delta_alt: %lf:", delta_alt, old_delta_alt);
00224         d_term_f=(p_term_f-p_term_f_old)/time_difference;
00225         d_term_l=(p_term_l-p_term_l_old)/time_difference;
00226         p_term_f_old=p_term_f;
00227         p_term_l_old=p_term_l;
00228     }
00229     integral_f_error+=p_term_f*time_difference;
00230     integral_l_error+=p_term_l*time_difference;
00231     last_vel_x_command=(Kp_plan*p_term_f+i_term_f*Ki_plan+Kd_plan*d_term_f)/10;
00232     last_vel_y_command=(Kp_plan*p_term_l+i_term_l*Ki_plan+Kd_plan*d_term_l)/10;
00233     printf("p_term_f: %lf p_term_l: %lf\n",p_term_f,p_term_l);
00234     *xvel_cmd=last_vel_x_command;
00235     *yvel_cmd=last_vel_y_command;
00236     }
00237 
00238 
00239   else{
00240     *xvel_cmd=last_vel_x_command;
00241     *yvel_cmd=last_vel_y_command;
00242   }
00243  }
00244 
00245   void calculate_yaw_desired(double *yaw_desired,double x_desired, double y_desired, double x_mes, double y_mes){
00246     double delta_x=x_desired-x_mes;
00247     double delta_y=y_desired-y_mes;
00248     if(sqrt(delta_x*delta_x+delta_y*delta_y)<1.5){
00249     *yaw_desired=old_yaw_desired;
00250     }
00251     else{
00252 
00253     double theta;
00254     if(delta_x!=0){
00255     theta=atan(delta_y/delta_x)/3.14159;
00256     }
00257     else{
00258     theta=1;
00259     }
00260     if(delta_y<0 && delta_x<0){
00261     theta+=1;
00262         if(theta>1){
00263             theta=theta-2;
00264         }
00265     }
00266     else if(delta_y>0 && delta_x<0){
00267     theta=abs(theta);
00268     }
00269     old_yaw_desired=theta;
00270     *yaw_desired=theta;
00271     }
00272 
00273   }
00274 
00275 
00276 // To send the command to the drone
00277 void sendControlToDrone(ControlCommand cmd)
00278 {
00279   geometry_msgs::Twist cmdT;
00280   cmdT.angular.z = cmd.yaw;
00281   cmdT.linear.z = cmd.gaz;
00282   cmdT.linear.x = cmd.pitch;
00283   cmdT.linear.y = cmd.roll;
00284 
00285   // assume that while actively controlling, the above for will never be equal to zero, so i will never hover.
00286   cmdT.angular.x = cmdT.angular.y = 0;
00287 
00288   if (isControlling)
00289   {
00290     vel_pub.publish(cmdT);
00291     // lastSentControl = cmd;
00292   }
00293 
00294   // lastControlSentMS = getMS(ros::Time::now());
00295 }
00296 
00297 int main(int argc, char **argv)
00298 {
00299   // Initialise the ROS client library. NoSigintHandler option to be able to manage the ctrl+c key ourselves here under.
00300   ros::init(argc, argv, "basic_controller", ros::init_options::NoSigintHandler);
00301 
00302   // Establish this program as a ROS node.
00303   ros::NodeHandle nh;
00304 
00305   // Override the default ros singint handler (must be set after the nodeHandle is created)
00306   signal(SIGINT, basic_sigint_handler);
00307 
00308   // Send some output as a log message.
00309   ROS_INFO_STREAM("Hello, ROS!");
00310 
00311   std::string navdata_channel = nh.resolveName("ardrone/navdata");
00312   std::string odometry_channel = nh.resolveName("ardrone/odometry");
00313   ros::Subscriber navdata_sub = nh.subscribe(navdata_channel, 10, &navdataCb);
00314   ros::Subscriber odometry_sub = nh.subscribe(odometry_channel, 10, &odometryCb);
00315 
00316   std::string control_channel = nh.resolveName("cmd_vel");
00317   std::string takeoff_channel = nh.resolveName("ardrone/takeoff");
00318   std::string land_channel = nh.resolveName("ardrone/land");
00319   std::string toggleState_channel = nh.resolveName("ardrone/reset");
00320 
00321   ros::Publisher toggleState_pub = nh.advertise<std_msgs::Empty>(toggleState_channel, 1, true);
00322   ros::Duration(1).sleep();
00323   ros::Publisher takeoff_pub = nh.advertise<std_msgs::Empty>(takeoff_channel, 1, true);
00324   land_pub = nh.advertise<std_msgs::Empty>(land_channel, 1);
00325   vel_pub = nh.advertise<geometry_msgs::Twist>(control_channel, 1);
00326 
00327   // Mission
00328   // toggleState_pub.publish(std_msgs::Empty());
00329   takeoff_pub.publish(std_msgs::Empty());
00330   ros::Duration(10).sleep();  // Wait for 10s
00331   isControlling = true;
00332 
00333   ROS_INFO_STREAM("Hello, ROS!");
00334 
00335   float alt_desired;
00336   double yaw_desired;
00337   float x_desired;
00338   float y_desired;
00339   ControlCommand cmd;
00340   double xvel_cmd;
00341   double yvel_cmd;
00342   double zvel_cmd;
00343   double yawvel_cmd;
00344 
00345 
00346   ros::Time tic;
00347   ros::Time toc;
00348   ros::Rate r(200);  // 200Hz
00349 
00350   // while not emergency land {
00351   alt_desired = 800;
00352   x_desired=0;
00353   y_desired=0;
00354   tic = ros::Time::now();
00355   toc = tic;
00356   ros::spinOnce();
00357   r.sleep();
00358   regu_old_time_yaw=lastOdometryReceived.header.stamp.sec+lastOdometryReceived.header.stamp.nsec/pow(10,9);
00359   regu_old_time_xy=lastOdometryReceived.header.stamp.sec+lastOdometryReceived.header.stamp.nsec/pow(10,9);
00360 
00361   while (ros::ok() && (toc - tic < ros::Duration(100)))
00362   {
00363    // ROS_INFO_STREAM("Check 3");
00364     calculate_yaw_desired(&yaw_desired,x_desired,y_desired,lastOdometryReceived.pose.pose.position.x,lastOdometryReceived.pose.pose.position.y);
00365     path_regu_altitude(&zvel_cmd, lastNavdataReceived.altd, alt_desired,lastNavdataReceived.tm);
00366     path_regu_yaw(&yawvel_cmd,lastOdometryReceived.pose.pose.orientation.z,yaw_desired,lastOdometryReceived.header.stamp.sec+lastOdometryReceived.header.stamp.nsec/pow(10,9));
00367     path_regu_xy(&xvel_cmd,&yvel_cmd,lastOdometryReceived.pose.pose.position.x,lastOdometryReceived.pose.pose.position.y,x_desired,y_desired,lastOdometryReceived.pose.pose.orientation.z,lastOdometryReceived.header.stamp.sec+lastOdometryReceived.header.stamp.nsec/pow(10,9));
00368 
00369     cmd=ControlCommand(xvel_cmd, yvel_cmd, yawvel_cmd, 0);
00370     printf("xvel_cmd: %lf     yvel_cmd: %lf\n", xvel_cmd,yvel_cmd);
00371 
00372     sendControlToDrone(cmd);
00373     ros::spinOnce();
00374     r.sleep();
00375     toc = ros::Time::now();
00376   }
00377 
00378   //}
00379 
00380   land_pub.publish(std_msgs::Empty());
00381 
00382   // let ROS do some stuff
00383   //
00384   ros::spin();
00385 
00386   /*
00387   while(ros::ok())
00388   {
00389     ros::spinOnce();
00390   }
00391   */
00392 }


ucl_drone
Author(s): dronesinma
autogenerated on Sat Jun 8 2019 20:51:53