Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 #include "flyer_controller/control_mode.h"
00035 #include "flyer_controller/hover_modes.h"
00036 
00037 #include "flyer_controller/control_mode_hover_info.h"
00038 
00039 namespace flyer_controller
00040 {
00041 class ControlModeHover : public HoverMode
00042 {
00043 protected:
00044   
00045   double pitch_deadband; 
00046   double roll_deadband; 
00047   double yaw_deadband; 
00048 
00049   double max_yaw_rate_cmd; 
00050   double waypoint_speed; 
00051   bool external_command_frame; 
00052   double external_frame_heading; 
00053 
00054   
00055   ros::Time last_control_output_time;
00056   bool first_joystick;
00057   bool moving_hover_point;
00058   bool adjusting_yaw;
00059 
00060 public:
00061   ControlModeHover() :
00062     HoverMode("hover"), 
00063         pitch_deadband(0.05), roll_deadband(0.05), yaw_deadband(0.1), 
00064         max_yaw_rate_cmd(10), waypoint_speed(0.25), external_command_frame(false), external_frame_heading(0), 
00065         first_joystick(true), moving_hover_point(false), adjusting_yaw(false)
00066   {
00067   }
00068 
00069   void onInit()
00070   {
00071     HoverMode::onInit();
00072     NODELET_WARN("Joystick must be properly calibrated using jscal.. have you done this?");
00073     
00074     nh_priv.param("pitch_deadband", pitch_deadband, pitch_deadband);
00075     nh_priv.param("roll_deadband", roll_deadband, roll_deadband);
00076     nh_priv.param("yaw_deadband", yaw_deadband, yaw_deadband);
00077     CHECK_PARAMETER((pitch_deadband >= 0) and (pitch_deadband <= 1), "parameter value out of range");
00078     CHECK_PARAMETER((roll_deadband >= 0) and (roll_deadband <= 1), "parameter value out of range");
00079     CHECK_PARAMETER((yaw_deadband >= 0) and (yaw_deadband <= 1), "parameter value out of range");
00080     nh_priv.param("max_yaw_rate_cmd", max_yaw_rate_cmd, max_yaw_rate_cmd);
00081     CHECK_PARAMETER(max_yaw_rate_cmd >= 0, "parameter value out of range");
00082     nh_priv.param("waypoint_speed", waypoint_speed, waypoint_speed);
00083     nh_priv.param("external_command_frame", external_command_frame, external_command_frame);
00084     nh_priv.param("external_frame_heading", external_frame_heading, external_frame_heading);
00085   }
00086 
00087   bool parseControlModeCmdDerived(const string cmd)
00088   {
00089     vector<string> words;
00090     boost::split(words, cmd, boost::is_any_of(" "));
00091     int nw = words.size();
00092     if (nw > 0)
00093     {
00094       if (words[0] == "adjust")
00095       {
00096         if ((nw == 3) and (words[1] == "hover_point"))
00097         {
00098           if (words[2] == "on")
00099           {
00100             if (not moving_hover_point)
00101             {
00102               moving_hover_point = true;
00103               NODELET_INFO("Hover point adjustment by joystick enabled");
00104             }
00105             else
00106               NODELET_ERROR("Hover point adjustment already enabled");
00107           }
00108           else if (words[2] == "off")
00109           {
00110             if (moving_hover_point)
00111             {
00112               moving_hover_point = false;
00113               NODELET_INFO("Hover point adjustment by joystick disabled");
00114             }
00115             else
00116               NODELET_ERROR("Hover point adjustment already disabled");
00117 
00118           }
00119           else
00120             NODELET_ERROR_STREAM("Invalid command '" << cmd << "'");
00121         }
00122         else if ((nw == 3) and (words[1] == "yaw"))
00123         {
00124           if (words[2] == "on")
00125           {
00126             if (not adjusting_yaw)
00127             {
00128               adjusting_yaw = true;
00129               NODELET_INFO("Yaw adjustment by joystick enabled");
00130             }
00131             else
00132               NODELET_ERROR("Yaw adjustment already enabled");
00133           }
00134           else if (words[2] == "off")
00135           {
00136             if (adjusting_yaw)
00137             {
00138               NODELET_INFO("Yaw adjustment by joystick disabled");
00139               adjusting_yaw = false;
00140             }
00141             else
00142               NODELET_ERROR("Yaw adjustment already disabled");
00143           }
00144           else
00145           {
00146             NODELET_ERROR_STREAM("Invalid command '" << cmd << "'");
00147           }
00148         }
00149         else
00150         {
00151           NODELET_ERROR_STREAM("Invalid command '" << cmd << "'");
00152         }
00153       }
00154       else
00155         return false; 
00156     }
00157     else
00158       return false; 
00159 
00160     return true;
00161   }
00162 
00163   
00164 
00165   void outputControl()
00166   {
00167     ros::Time now_time = ros::Time::now();
00168     if (first_joystick)
00169     {
00170       last_control_output_time = now_time;
00171       first_joystick = false;
00172       return;
00173     }
00174     double dt = (now_time - last_control_output_time).toSec();
00175 
00176     if (moving_hover_point)
00177     {
00178       
00179       double cos_ang, sin_ang;
00180       if (external_command_frame)
00181       {
00182         cos_ang = cos(angles::from_degrees(external_frame_heading));
00183         sin_ang = sin(angles::from_degrees(external_frame_heading));
00184       }
00185       else
00186       {
00187         double current_yaw, current_pitch, current_roll;
00188         odom_msg_to_ypr(boost::make_shared<nav_msgs::Odometry>(latest_state), current_yaw, current_pitch, current_roll);
00189         cos_ang = cos(current_yaw);
00190         sin_ang = sin(current_yaw);
00191       }
00192       double north_cmd_normalized = -sin_ang * latest_opercmd.roll_cmd - cos_ang * latest_opercmd.pitch_cmd;
00193       double east_cmd_normalized = cos_ang * latest_opercmd.roll_cmd - sin_ang * latest_opercmd.pitch_cmd;
00194       double north_vel_cmd_new = north_cmd_normalized * waypoint_speed;
00195       double east_vel_cmd_new = east_cmd_normalized * waypoint_speed;
00196       double north_cmd_new = north_cmd + north_vel_cmd_new * dt;
00197       double east_cmd_new = east_cmd + east_vel_cmd_new * dt;
00198       if (hover_point_within_bounds(north_cmd_new, east_cmd_new))
00199       {
00200         north_vel_cmd = north_vel_cmd_new;
00201         east_vel_cmd = east_vel_cmd_new;
00202         north_cmd = north_cmd_new;
00203         east_cmd = east_cmd_new;
00204       }
00205       else
00206       {
00207         north_vel_cmd = 0.0;
00208         east_vel_cmd = 0.0;
00209         NODELET_ERROR_THROTTLE(1, "Cannot move hover point out of bounds");
00210       }
00211     }
00212 
00213     
00214 
00215     if (adjusting_yaw)
00216       yaw_cmd = angles::to_degrees(
00217                                    angles::normalize_angle(
00218                                                            angles::from_degrees(
00219                                                                                 yaw_cmd + latest_opercmd.yaw_cmd
00220                                                                                     * max_yaw_rate_cmd * dt)));
00221 
00222     
00223     
00224     
00225     
00226     
00227     
00228     
00229     
00230 
00231     last_control_output_time = now_time;
00232 
00233     HoverMode::outputControl();
00234   }
00235   
00236   
00237   
00238 
00239 }; 
00240 PLUGINLIB_DECLARE_CLASS(flyer_controller, ControlModeHover, flyer_controller::ControlModeHover, nodelet::Nodelet)
00241 ;
00242 
00243 }
00244