00001
00002
00003
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
00018 double Kd_plan=0;
00019
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;
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
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
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
00090 cmdT.angular.x = cmdT.angular.y = 0;
00091
00092
00093 vel_pub.publish(cmdT);
00094
00095
00096 land_pub.publish(std_msgs::Empty());
00097 ros::shutdown();
00098 }
00099
00100
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;
00105 double i_term;
00106
00107 double time_difference=(regu_new_time_z-regu_old_time_z)/1000;
00108
00109
00110 if(time_difference!=0){
00111
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;
00119 if(time_difference!=0){
00120
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
00130
00131
00132
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
00143 double p_term;
00144 double d_term=0;
00145 double i_term;
00146
00147 double time_difference=(regu_new_time-regu_old_time_yaw)/1000;
00148 double new_vel_yaw_cmd;
00149
00150
00151 if(time_difference!=0){
00152
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;
00161 if(time_difference!=0)
00162 {
00163
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
00171
00172
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
00182
00183
00184
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;
00197 double i_term_l;
00198 double p_term_f;
00199 double d_term_f=0;
00200 double i_term_f;
00201
00202 double time_difference=(regu_new_time_xy-regu_old_time_xy)/1000;
00203
00204
00205 if(time_difference!=0){
00206 if(x_desired_old!=x_desired||y_desired_old!=y_desired){
00207 integral_xy_error=0;
00208 }
00209
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
00216
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
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
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
00286 cmdT.angular.x = cmdT.angular.y = 0;
00287
00288 if (isControlling)
00289 {
00290 vel_pub.publish(cmdT);
00291
00292 }
00293
00294
00295 }
00296
00297 int main(int argc, char **argv)
00298 {
00299
00300 ros::init(argc, argv, "basic_controller", ros::init_options::NoSigintHandler);
00301
00302
00303 ros::NodeHandle nh;
00304
00305
00306 signal(SIGINT, basic_sigint_handler);
00307
00308
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
00328
00329 takeoff_pub.publish(std_msgs::Empty());
00330 ros::Duration(10).sleep();
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);
00349
00350
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
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
00383
00384 ros::spin();
00385
00386
00387
00388
00389
00390
00391
00392 }