00001
00015 #include "ucl_drone/controller.h"
00016
00017 static bool urgency_signal = false;
00018
00019
00020 BasicController::BasicController()
00021 {
00022 std::string drone_prefix;
00023 ros::param::get("~drone_prefix", drone_prefix);
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 pose_channel = nh.resolveName("pose_estimation");
00040 pose_sub = nh.subscribe(pose_channel, 10, &BasicController::poseCb, this);
00041 poseref_channel = nh.resolveName("path_planning");
00042 poseref_sub = nh.subscribe(poseref_channel, 10, &BasicController::poseRefCb, this);
00043
00044
00045 control_channel = nh.resolveName(drone_prefix + "cmd_vel");
00046 vel_pub = nh.advertise< geometry_msgs::Twist >(control_channel, 1);
00047
00048 takeoff_channel = nh.resolveName(drone_prefix + "ardrone/takeoff");
00049 takeoff_pub = nh.advertise< std_msgs::Empty >(takeoff_channel, 1, true);
00050
00051 land_channel = nh.resolveName(drone_prefix + "ardrone/land");
00052 land_pub = nh.advertise< std_msgs::Empty >(land_channel, 1);
00053
00054 toggleState_channel = nh.resolveName(drone_prefix + "ardrone/reset");
00055 toggleState_pub = nh.advertise< std_msgs::Empty >(toggleState_channel, 1, true);
00056
00057 reset_channel = nh.resolveName("reset_pose");
00058 reset_pub = nh.advertise< std_msgs::Empty >(reset_channel, 1, true);
00059
00060
00061 startControl_ =
00062 nh.advertiseService("drone_ucl/start_control", &BasicController::startControl, this);
00063
00064 stopControl_ = nh.advertiseService("drone_ucl/stop_control", &BasicController::stopControl, this);
00065
00066
00067
00068
00069 alt_ref = 1.0;
00070 x_ref = 0.0;
00071 y_ref = 0.0;
00072 yaw_ref = 0.0;
00073 isControlling = false;
00074
00075
00076
00077
00078
00079
00080
00081 Kp_alt = 1.8;
00082 Ki_alt = 0;
00083 Kd_alt = 2;
00084
00085
00086
00087
00088 Kp_yaw = 3;
00089 Ki_yaw = 0;
00090 Kd_yaw = 0.3;
00091
00092
00093
00094 Kp_plan = 0.06;
00095 Ki_plan = 0.002;
00096 Kd_plan = 0.2;
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 anti_windup_yaw = 0.5;
00107
00108
00109 alt_desired_old = 0;
00110 yaw_desired_old = 0;
00111 x_desired_old = 0;
00112 y_desired_old = 0;
00113 old_yaw_desired = 0;
00114 }
00115
00116 BasicController::~BasicController()
00117 {
00118 }
00119
00120
00121
00122 bool BasicController::startControl(std_srvs::Empty::Request& req, std_srvs::Empty::Response& res)
00123 {
00124 ROS_INFO("calling service start");
00125 takeoff_pub.publish(std_msgs::Empty());
00126 sendVelToDrone(0, 0, 0, 0,
00127 true);
00128
00129 isControlling = true;
00130 ros::Duration(8).sleep();
00131
00132 std_msgs::Empty msg;
00133 reset_pub.publish(msg);
00134 sendVelToDrone(0, 0, 0, 0, true);
00135 ros::Duration(5).sleep();
00136 return true;
00137 }
00138
00139 bool BasicController::stopControl(std_srvs::Empty::Request& req, std_srvs::Empty::Response& res)
00140 {
00141
00142 sendVelToDrone(0, 0, 0, 0);
00143
00144 isControlling = false;
00145 land_pub.publish(std_msgs::Empty());
00146 return true;
00147 }
00148
00149
00150
00151
00152
00153 void BasicController::reguXY(double* xvel_cmd, double* yvel_cmd, double x_mes, double y_mes,
00154 double x_desired, double y_desired, double yaw,
00155 double regu_new_time_xy)
00156 {
00157
00158 double p_term_l;
00159 double d_term_l = 0;
00160 double i_term_l;
00161 double p_term_f;
00162 double d_term_f = 0;
00163 double i_term_f;
00164
00165 double time_difference = (regu_new_time_xy - regu_old_time_xy);
00166
00167
00168 if (time_difference != 0)
00169 {
00170 if (x_desired_old != x_desired ||
00171 y_desired_old != y_desired)
00172 {
00173 integral_xy_error = 0;
00174 }
00175 double dist = sqrt(pow((x_mes - x_desired), 2) + pow((y_mes - y_desired), 2));
00176 dist_old = dist;
00177 double delta_x = x_desired - x_mes;
00178 double delta_y = y_desired - y_mes;
00179 regu_old_time_xy = regu_new_time_xy;
00180
00181
00182
00183 double c_theta = cos(yaw);
00184 double s_theta = sin(yaw);
00185
00186
00187
00188 p_term_f = delta_x * c_theta - delta_y * s_theta;
00189 p_term_l = delta_x * s_theta + delta_y * c_theta;
00190
00191
00192 d_term_f = (p_term_f - p_term_f_old) / time_difference;
00193 d_term_l = (p_term_l - p_term_l_old) / time_difference;
00194 p_term_f_old = p_term_f;
00195 p_term_l_old = p_term_l;
00196
00197
00198 i_term_f += p_term_f * time_difference;
00199 i_term_l += p_term_l * time_difference;
00200 last_vel_x_command = (Kp_plan * p_term_f + i_term_f * Ki_plan + Kd_plan * d_term_f);
00201 last_vel_y_command = (Kp_plan * p_term_l + i_term_l * Ki_plan + Kd_plan * d_term_l);
00202
00203
00204 *xvel_cmd = last_vel_x_command;
00205 *yvel_cmd = last_vel_y_command;
00206 }
00207
00208 else
00209 {
00210 *xvel_cmd = last_vel_x_command;
00211 *yvel_cmd = last_vel_y_command;
00212 }
00213 }
00214
00215
00216 void BasicController::reguAltitude(double* zvel_cmd, double alt_mes, double alt_desired,
00217 double regu_new_time_z)
00218 {
00219 double p_term;
00220 double d_term = 0;
00221 double i_term;
00222
00223 double time_difference = (regu_new_time_z - regu_old_time_z);
00224
00225 if (time_difference != 0)
00226 {
00227 if (alt_desired_old != alt_desired)
00228 {
00229 integral_alt_error = 0;
00230 }
00231
00232 alt_desired_old = alt_desired;
00233 regu_old_time_z = regu_new_time_z;
00234
00235 double delta_alt = -alt_mes + alt_desired;
00236
00237
00238
00239 p_term = delta_alt;
00240
00241
00242 if (time_difference != 0)
00243 {
00244 d_term = (delta_alt - old_delta_alt) / time_difference;
00245 old_delta_alt = delta_alt;
00246 }
00247
00248 integral_alt_error += delta_alt * time_difference;
00249
00250
00251
00252 i_term = integral_alt_error;
00253
00254
00255
00256 last_vel_z_command = (Kp_alt * p_term + i_term * Ki_alt + Kd_alt * d_term);
00257
00258 *zvel_cmd = last_vel_z_command;
00259
00260
00261
00262
00263 }
00264 else
00265 {
00266 *zvel_cmd = last_vel_z_command;
00267 }
00268 }
00269
00270
00271 void BasicController::reguYaw(double* yawvel_cmd, double yaw_mes, double yaw_desired,
00272 double regu_new_time)
00273 {
00274
00275 double p_term;
00276 double d_term = 0;
00277 double i_term;
00278
00279 double time_difference = (regu_new_time - regu_old_time_yaw);
00280 double new_vel_yaw_cmd;
00281
00282
00283 if (time_difference != 0)
00284 {
00285 if (yaw_desired_old != yaw_desired)
00286 {
00287 integral_yaw_error = 0;
00288 }
00289 yaw_desired_old = yaw_desired;
00290 regu_old_time_yaw = regu_new_time;
00291 double delta_yaw = -yaw_mes + yaw_desired;
00292
00293
00294
00295
00296
00297
00298 if (delta_yaw > 3.14159)
00299 {
00300 delta_yaw -= 2 * 3.14159;
00301 }
00302 else if (delta_yaw < -3.14159)
00303 {
00304 delta_yaw += 2 * 3.14159;
00305 }
00306 p_term = delta_yaw;
00307 if (time_difference != 0)
00308 {
00309 d_term = (delta_yaw - old_delta_yaw) / time_difference;
00310 old_delta_yaw = delta_yaw;
00311 }
00312 integral_yaw_error += delta_yaw * time_difference;
00313 i_term = integral_yaw_error;
00314 new_vel_yaw_cmd = (Kp_yaw * p_term + i_term * Ki_yaw + Kd_yaw * d_term);
00315
00316
00317 if (new_vel_yaw_cmd > anti_windup_yaw)
00318 {
00319 new_vel_yaw_cmd = anti_windup_yaw;
00320 }
00321 else if (new_vel_yaw_cmd < -anti_windup_yaw)
00322 {
00323 new_vel_yaw_cmd = -anti_windup_yaw;
00324 }
00325
00326
00327 last_vel_yaw_command = new_vel_yaw_cmd;
00328 *yawvel_cmd = last_vel_yaw_command;
00329 }
00330 else
00331 {
00332 *yawvel_cmd = last_vel_yaw_command;
00333 }
00334 }
00335
00336
00337 void BasicController::sendVelToDrone(double pitch, double roll, double yaw_vel, double zvel_cmd,
00338 bool force )
00339 {
00340 geometry_msgs::Twist cmdT;
00341 cmdT.angular.z = yaw_vel;
00342 cmdT.linear.z = zvel_cmd;
00343 cmdT.linear.x = pitch;
00344 cmdT.linear.y = roll;
00345
00346
00347
00348
00349 cmdT.angular.x = cmdT.angular.y = 0;
00350
00351 if (isControlling || force)
00352 {
00353 vel_pub.publish(cmdT);
00354 }
00355 }
00356
00357
00358
00359 void BasicController::poseCb(const ucl_drone::Pose3D::ConstPtr posePtr)
00360 {
00361 lastPoseReceived = *posePtr;
00362 }
00363
00364
00365
00366 void BasicController::poseRefCb(const ucl_drone::PoseRef::ConstPtr poseRefPtr)
00367 {
00368 lastPoseRefReceived = *poseRefPtr;
00369 }
00370
00371
00372
00373 void BasicController::controlLoop()
00374 {
00375 double xvel_cmd;
00376 double yvel_cmd;
00377 double yawvel_cmd;
00378 double zvel_cmd;
00379
00380 reguXY(&xvel_cmd, &yvel_cmd, lastPoseReceived.x, lastPoseReceived.y, lastPoseRefReceived.x,
00381 lastPoseRefReceived.y, lastPoseReceived.rotZ,
00382 lastPoseReceived.header.stamp.sec + lastPoseReceived.header.stamp.nsec / pow(10, 9));
00383 reguYaw(&yawvel_cmd, lastPoseReceived.rotZ, lastPoseRefReceived.rotZ,
00384 lastPoseReceived.header.stamp.sec + lastPoseReceived.header.stamp.nsec / pow(10, 9));
00385 reguAltitude(&zvel_cmd, lastPoseReceived.z, lastPoseRefReceived.z,
00386 lastPoseReceived.header.stamp.sec + lastPoseReceived.header.stamp.nsec / pow(10, 9));
00387
00388 sendVelToDrone(xvel_cmd, yvel_cmd, yawvel_cmd, zvel_cmd, false);
00389
00390
00391 if (lastPoseRefReceived.landAndStop)
00392 {
00393 std_srvs::Empty::Request req;
00394 std_srvs::Empty::Response res;
00395 stopControl(req, res);
00396 }
00397
00398 if (lastPoseRefReceived.takeoffAndStart && !isControlling)
00399 {
00400
00401 std_srvs::Empty::Request req;
00402 std_srvs::Empty::Response res;
00403 startControl(req, res);
00404 }
00405
00406
00407 if (urgency_signal)
00408 {
00409 std_srvs::Empty::Request req;
00410 std_srvs::Empty::Response res;
00411 stopControl(req, res);
00412 ros::shutdown();
00413 }
00414 }
00415
00417 static void basicSigintHandler(int sig)
00418 {
00419 urgency_signal = true;
00420 }
00421
00422
00423 int main(int argc, char** argv)
00424 {
00425 ros::init(argc, argv, "controller", ros::init_options::NoSigintHandler);
00426 signal(SIGINT, basicSigintHandler);
00427 BasicController bc;
00428 ROS_INFO_STREAM("controller started!");
00429 while (ros::ok())
00430 {
00431 TIC(control);
00432 bc.controlLoop();
00433 TOC(control, "control");
00434 ros::spinOnce();
00435 }
00436 return 0;
00437 }