control_mode_hover.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2010, UC Regents
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the University of California nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *********************************************************************/
00034 #include "flyer_controller/control_mode.h"
00035 #include "flyer_controller/hover_modes.h"
00036 // msg:
00037 #include "flyer_controller/control_mode_hover_info.h"
00038 
00039 namespace flyer_controller
00040 {
00041 class ControlModeHover : public HoverMode
00042 {
00043 protected:
00044   // Parameters
00045   double pitch_deadband; // joystick units, 0.1 = 10% of half-range
00046   double roll_deadband; // joystick units, 0.1 = 10% of half-range
00047   double yaw_deadband; // joystick units, 0.1 = 10% of half-range
00048 
00049   double max_yaw_rate_cmd; // [deg/s] yaw rate corresponding to full deflection
00050   double waypoint_speed; // [m/s] lateral speed at which to move the controller setpoint between autosequence points
00051   bool external_command_frame; // should commands be interpreted w.r.t. an external frame?
00052   double external_frame_heading; // [deg] heading that will correspond to a -pitch command when using external frame
00053 
00054   // Members
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     // Parameters
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; // unknown first word
00156     }
00157     else
00158       return false; // command empty
00159 
00160     return true;
00161   }
00162 
00163   // TODO: rework the following in light of joystick overhaul..
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       // Now, interpret pitch and roll as translational velocity commands:
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     // Adjust yaw setpoint if applicable:
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     //    else if (moving_hover_point)
00223     //    {
00224     //      moving_hover_point = false;
00225     //      double current_x, current_y, current_z;
00226     //      odom_msg_to_xyz(boost::make_shared<nav_msgs::Odometry>(latest_state), current_x, current_y, current_z);
00227     //      north_cmd = current_x;
00228     //      east_cmd = current_y;
00229     //    }
00230 
00231     last_control_output_time = now_time;
00232 
00233     HoverMode::outputControl();
00234   }
00235   //  void process_joystick(const sensor_msgs::JoyConstPtr & joy_msg)
00236   //  {
00237   //  }
00238 
00239 }; // class
00240 PLUGINLIB_DECLARE_CLASS(flyer_controller, ControlModeHover, flyer_controller::ControlModeHover, nodelet::Nodelet)
00241 ;
00242 
00243 }
00244 // namespace


flyer_controller
Author(s): Patrick Bouffard
autogenerated on Sun Jan 5 2014 11:37:53