hover_modes.h
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 <string>
00035 #include <vector>
00036 #include <map>
00037 #include <algorithm>
00038 #include <boost/algorithm/string.hpp>
00039 #include "flyer_controller/control_mode.h"
00040 #include "flyer_controller/control_mode_hover_info.h"
00041 #include "flyer_controller/control_utils.h"
00042 #include "flyer_controller/pid.h"
00043 //#include <visualization_msgs/Marker.h>
00044 //#include <visualization_msgs/MarkerArray.h>
00045 #include <angles/angles.h>
00046 
00047 using std::string;
00048 using std::vector;
00049 using std::map;
00050 using std::max;
00051 using std::min;
00052 using angles::to_degrees;
00053 using angles::from_degrees;
00054 
00055 const double GRAVITY = 9.81; // m/s/s
00056 
00057 namespace flyer_controller
00058 {
00059 
00060 struct hover_point
00061 {
00062   string name;
00063   double north; // [m]
00064   double east; // [m]
00065   double north_vel; // [m/s]
00066   double east_vel; // [m/s]
00067   double yaw; // [deg]
00068 };
00069 
00070 class HoverMode : public ControlMode
00071 {
00072 protected:
00073   // Params
00074   double max_alt_cmd; // [m] commanded altitude corresponding to full + deflection
00075   double min_alt_cmd; // [m] commanded altitude corresponding to full - deflection
00076   // next two meaningless unless/until 'manual hover' implemented:
00077   //  bool external_command_frame; // should commands be interpreted w.r.t. an external frame?
00078   //  double external_frame_heading; // [deg] heading that will correspond to a -pitch command when using external frame
00079   double KP; // deg/m
00080   double KI; // deg/(m-s)
00081   double KD; // deg/m/s
00082   double Ilimit; // deg
00083   bool direct_thrust_control; // set true to do thrust control directly in hover controller
00084   double alt_KP; // N per meter
00085   double alt_KI; // N per meter-second
00086   double alt_KD; // N counts per m/s
00087   double alt_Ilimit; // N
00088   double mass; // kg - nominal thrust will be based on this value
00089   double north_cmd_max; // m - disallow commanding north values greater than this
00090   double north_cmd_min; // m - disallow commanding north values less than this
00091   double east_cmd_max; // m - disallow commanding east values greater than this
00092   double east_cmd_min; // m - disallow commanding east values less than this
00093 
00094   // Publisher
00095   ros::Publisher info_pub;
00096   //  ros::Publisher marker_pub;
00097   //  ros::Publisher marker_array_pub;
00098   // Member vars
00099   string mode_name_;
00100   control_mode_output control_out;
00101   double yaw_cmd; // [deg]
00102   flyer_controller::Pid north_pid;
00103   flyer_controller::Pid east_pid;
00104   flyer_controller::Pid alt_pid;
00105   double north_cmd;
00106   double east_cmd;
00107   double alt_cmd;
00108   double north_vel_cmd;
00109   double east_vel_cmd;
00110   double north_err;
00111   double east_err;
00112   double alt_err; // used with direct_thrust_control only
00113   double north_vel_err;
00114   double east_vel_err;
00115   map<string, hover_point> hover_points;
00116   hover_point current_hover_point;
00117   double alt_override;
00118   double yaw_override;
00119   bool yaw_override_active;
00120   ros::Time last_time;
00121   bool first;
00122 
00123 public:
00124 
00125   HoverMode(string mode_name) :
00126         //    external_command_frame(false), external_frame_heading(0),
00127         max_alt_cmd(1.5), min_alt_cmd(0.0), KP(12), KI(1),
00128         KD(8),
00129         Ilimit(2), //
00130         direct_thrust_control(false), alt_KP(2), alt_KI(1), alt_KD(2),
00131         alt_Ilimit(5),
00132         mass(1.3), //
00133         mode_name_(mode_name), yaw_cmd(0), north_cmd(0), east_cmd(0), alt_cmd(0), north_vel_cmd(0), east_vel_cmd(0),
00134         north_err(0), east_err(0), north_vel_err(0), east_vel_err(0), alt_override(9999), yaw_override(0),
00135         yaw_override_active(false), first(true)
00136   {
00137 
00138   }
00139 
00140   void onInit()
00141   {
00142     NODELET_INFO("ControlModeHover onInit() called");
00143     ControlMode::onInit();
00144     // Parameters
00145     nh_priv.param("max_alt_cmd", max_alt_cmd, max_alt_cmd);
00146     nh_priv.param("min_alt_cmd", min_alt_cmd, min_alt_cmd);
00147     nh_priv.param("KP", KP, KP);
00148     nh_priv.param("KI", KI, KI);
00149     nh_priv.param("KD", KD, KD);
00150     nh_priv.param("Ilimit", Ilimit, Ilimit);
00151     nh_priv.param("direct_thrust_control", direct_thrust_control, direct_thrust_control);
00152     nh_priv.param("alt_KP", alt_KP, alt_KP);
00153     nh_priv.param("alt_KI", alt_KI, alt_KI);
00154     nh_priv.param("alt_KD", alt_KD, alt_KD);
00155     nh_priv.param("alt_Ilimit", alt_Ilimit, alt_Ilimit);
00156     nh_priv.param("mass", mass, mass);
00157     nh_priv.param("north_cmd_max", north_cmd_max, north_cmd_max);
00158     nh_priv.param("north_cmd_min", north_cmd_min, north_cmd_min);
00159     nh_priv.param("east_cmd_max", east_cmd_max, east_cmd_max);
00160     nh_priv.param("east_cmd_min", east_cmd_min, east_cmd_min);
00161 
00162     // Publishers
00163     //    marker_pub = nh_priv.advertise<visualization_msgs::Marker> ("marker", 10, true);
00164     //    marker_array_pub = nh_priv.advertise<visualization_msgs::MarkerArray> ("marker_array", 10, true);
00165 
00166     // North and East PID control
00167     set_gains(KP, KI, KD, Ilimit);
00168     // Altitude PID control (optional)
00169     if (direct_thrust_control)
00170       alt_pid.initPid(alt_KP, alt_KI, alt_KD, alt_Ilimit, -alt_Ilimit);
00171 
00172     requestRegistration(mode_name_);
00173     control_out.control_mode = mode_name_;
00174     control_out.motors_on = false;
00175   }
00176 
00177 private:
00178   // Parses (and acts upon if appropriate) a control_mode_command.Returns true if the command
00179   // was recognized and false otherwise. Note that an invalid (but still recognized) command
00180   // should only emit an error message but *not* also return false.
00181   bool parseControlModeCmd(const string cmd)
00182   {
00183     vector<string> words;
00184     boost::split(words, cmd, boost::is_any_of(" "));
00185     int nw = words.size();
00186     if (nw > 0)
00187     {
00188       if (words[0] == "mode")
00189       {
00190         parse_mode(words);
00191       }
00192       else if (words[0] == "define")
00193       // define hover_point point_name north_coord east_coord [north_vel east_vel [yaw_coord]]
00194 
00195       {
00196         if (words[1] == "hover_point")
00197         {
00198           parse_define_hover_point(words);
00199         }
00200         else
00201         {
00202           return false;
00203         }
00204       }
00205       else if (words[0] == "set")
00206       {
00207         if (nw > 1)
00208         {
00209           if (words[1] == "hover_point")
00210           {
00211             parse_set_hover_point(words);
00212 
00213           }
00214           else if (words[1] == "gains")
00215           {
00216             parse_set_gains(words);
00217           }
00218         }
00219         else
00220         {
00221           return false;
00222         }
00223       }
00224       else if (words[0] == "alt_override")
00225       {
00226         if (nw == 2)
00227         {
00228           alt_override = atof(words[1].c_str());
00229           NODELET_INFO_STREAM("alt_override set to " << alt_override);
00230         }
00231         else
00232         {
00233           NODELET_ERROR_STREAM("Invalid command '" << cmd << "'");
00234         }
00235       }
00236       else if (words[0] == "yaw_override")
00237       {
00238         if (nw == 2)
00239         {
00240           if (words[1] == "off" and yaw_override_active)
00241           {
00242             yaw_override_active = false;
00243             NODELET_INFO("yaw_override OFF");
00244           }
00245           else
00246           {
00247             yaw_override_active = true;
00248             yaw_override = atof(words[1].c_str());
00249             yaw_cmd = yaw_override;
00250             NODELET_INFO_STREAM("yaw_override set to " << yaw_override);
00251           }
00252         }
00253         else
00254         {
00255           NODELET_ERROR_STREAM("Invalid command '" << cmd << "'");
00256         }
00257       }
00258       else
00259       {
00260         return false;
00261       }
00262     }
00263     return true;
00264   }
00265 
00266 protected:
00267   // Actual hover mode classes should implement this method if they are to respond
00268   // to additional commands. It is called if parseControlModeCmd returns false.
00269   // The default implementation returns false so that an unrecognized command
00270   // will result in an error even if the derived class doesn't implement this method.
00271   virtual bool parseControlModeCmdDerived(const string cmd)
00272   {
00273     return false;
00274   }
00275 
00276 private:
00277   void controlModeCmdCallback(const control_mode_cmdConstPtr& msg)
00278   {
00279     NODELET_DEBUG_STREAM("Heard command: " << msg->cmd);
00280     if (!parseControlModeCmd(msg->cmd))
00281     {
00282       if (!parseControlModeCmdDerived(msg->cmd))
00283       {
00284         NODELET_ERROR_STREAM("Unrecognized command: " << msg->cmd);
00285       }
00286     }
00287   }
00288 
00289   // Virtual methods from base class
00290 protected:
00291   void outputControl()
00292   {
00293     //control_mode_output control_out;
00294     bool do_calcs = false;
00295     bool do_publish = false;
00296     ros::Time now_time = ros::Time::now();
00297     ros::Duration dt;
00298     if (first)
00299     {
00300       first = false;
00301       last_time = now_time;
00302       return;
00303     }
00304     else if (state_updated)
00305     {
00306       dt = now_time - last_time;
00307       last_time = now_time;
00308     }
00309     static int prev_trigger = 0;
00310     control_out.header.stamp = now_time;
00311 
00312     switch (state)
00313     {
00314       case ControlModeTypes::STANDBY:
00315         do_calcs = (got_first_joy and got_first_state);
00316         do_publish = true;
00317         break;
00318       case ControlModeTypes::ACTIVE:
00319         do_calcs = state_updated; // if no state updates, keep last command
00320         do_publish = true;
00321         break;
00322       default:
00323         break;
00324     }
00325 
00326     if (do_calcs)
00327     {
00328       //      if (not state_updated and state == ControlModeTypes::ACTIVE)
00329       //      {
00330       //        ROS_INFO("state not updated since last iteration");
00331       //      }
00332       double current_yaw, current_pitch, current_roll; // radians
00333       double current_vx, current_vy, current_vz;
00334       odom_msg_to_ypr(boost::make_shared<nav_msgs::Odometry>(latest_state), current_yaw, current_pitch, current_roll);
00335       odom_msg_to_lin_vel(boost::make_shared<nav_msgs::Odometry>(latest_state), current_vx, current_vy, current_vz);
00336       state_updated = false;
00337       get_current_lateral_position_errors(north_err, east_err, alt_err);
00338       north_vel_err = current_vx - north_vel_cmd;
00339       east_vel_err = current_vy - east_vel_cmd;
00340       if (latest_opercmd.motors_on and prev_trigger == 0)
00341       {
00342         north_pid.reset();
00343         east_pid.reset();
00344         if (direct_thrust_control)
00345           alt_pid.reset();
00346       }
00347       north_pid.updatePid(north_err, north_vel_err, dt);
00348       east_pid.updatePid(east_err, east_vel_err, dt);
00349       if (direct_thrust_control)
00350         alt_pid.updatePid(alt_err, dt);
00351       double tilt_north_cmd = north_pid.getCurrentCmd();
00352       double tilt_east_cmd = east_pid.getCurrentCmd();
00353       // Rotate into body frame:
00354       double cos_yaw = cos(current_yaw);
00355       double sin_yaw = sin(current_yaw);
00356       control_out.roll_cmd = tilt_east_cmd * cos_yaw - tilt_north_cmd * sin_yaw;
00357       control_out.pitch_cmd = -tilt_east_cmd * sin_yaw - tilt_north_cmd * cos_yaw;
00358       prev_trigger = latest_opercmd.motors_on;
00359       control_out.direct_yaw_rate_commands = false;
00360       control_out.yaw_cmd = yaw_cmd;
00361       control_out.yaw_rate_cmd = 0; //std::numeric_limits<double>::quiet_NaN();
00362       control_out.direct_thrust_commands = direct_thrust_control;
00363       if (direct_thrust_control)
00364       {
00365         control_out.alt_cmd = 0.0;
00366         control_out.thrust_cmd = GRAVITY * mass + alt_pid.getCurrentCmd();
00367       }
00368       else
00369       {
00370         control_out.alt_cmd = min(alt_override, min_alt_cmd + (max_alt_cmd - min_alt_cmd) * latest_opercmd.alt_cmd);
00371       }
00372     } // do_calcs
00373 
00374     control_out.motors_on = (got_first_joy and (latest_opercmd.motors_on));
00375     if (do_publish)
00376     {
00377       control_out.control_mode = mode_name_;
00378       output_pub.publish(control_out);
00379     }
00380 
00381   }
00382 
00383 protected:
00384   void get_current_lateral_position_errors(double &north_err, double &east_err, double &alt_err)
00385   {
00386     double current_x, current_y, current_z;
00387     odom_msg_to_xyz(boost::make_shared<nav_msgs::Odometry>(latest_state), current_x, current_y, current_z);
00388     north_err = current_x - north_cmd;
00389     east_err = current_y - east_cmd;
00390     alt_err = -current_z - alt_cmd;
00391   }
00392 
00393   void get_current_lateral_position(double &current_x, double &current_y)
00394   {
00395     double current_z;
00396     odom_msg_to_xyz(boost::make_shared<nav_msgs::Odometry>(latest_state), current_x, current_y, current_z);
00397   }
00398 
00399   void get_current_error_to_point(const hover_point& point, double &north_err, double &east_err, double &yaw_err)
00400   {
00401     double current_x, current_y, current_z;
00402     odom_msg_to_xyz(boost::make_shared<nav_msgs::Odometry>(latest_state), current_x, current_y, current_z);
00403     north_err = current_x - point.north;
00404     east_err = current_y - point.east;
00405     get_current_yaw_error(point.yaw, yaw_err);
00406   }
00407 
00408   void get_current_yaw_error(const double yaw_cmd, double &yaw_err)
00409   {
00410     if (not isnan(yaw_cmd))
00411     {
00412       double current_yaw, current_pitch, current_roll;
00413       odom_msg_to_ypr(boost::make_shared<nav_msgs::Odometry>(latest_state), current_yaw, current_pitch, current_roll);
00414       yaw_err = angles::shortest_angular_distance(current_yaw, angles::from_degrees(yaw_cmd));
00415     }
00416     else
00417     {
00418       yaw_err = 0.0;
00419     }
00420   }
00421 
00422 protected:
00423   void reportStatusTimerCallback(const ros::TimerEvent& e)
00424   {
00425     control_mode_status msg;
00426     //NODELET_INFO_STREAM(__PRETTY_FUNCTION__);
00427     msg.state = state;
00428     msg.info = info;
00429     msg.header.stamp = e.current_real;
00430     ready = (got_first_joy and got_first_state);
00431     //    NODELET_INFO_STREAM("got_first_joy = " << got_first_joy << " got_first_state = " << got_first_state);
00432     msg.ready = ready; // TODO: check some more conditions..
00433     control_mode_status_pub.publish(msg);
00434 
00435     if ((state == ControlModeTypes::STANDBY) or (state == ControlModeTypes::ACTIVE))
00436     {
00437       control_mode_hover_info info_msg;
00438       info_msg.header.stamp = e.current_real;
00439       info_msg.hover_point = current_hover_point.name;
00440 
00441       info_msg.north_cmd = north_cmd;
00442       info_msg.east_cmd = east_cmd;
00443       info_msg.north_vel_cmd = north_vel_cmd;
00444       info_msg.east_vel_cmd = east_vel_cmd;
00445       info_msg.yaw_cmd = yaw_cmd;
00446       info_msg.alt_override = alt_override;
00447 
00448       info_msg.north_err = north_err;
00449       info_msg.east_err = east_err;
00450       info_msg.north_vel_err = north_vel_err;
00451       info_msg.east_vel_err = east_vel_err;
00452       double yaw_err;
00453       get_current_yaw_error(yaw_cmd, yaw_err);
00454       info_msg.yaw_err = yaw_err;
00455 
00456       info_pub.publish(info_msg);
00457     }
00458     diag_updater.update();
00459   }
00460 
00461 private:
00462   // Command parsers
00463   void parse_mode(const vector<string> &words)
00464   {
00465     int nw = words.size();
00466     if (nw == 2)
00467     {
00468       string newmode = words[1];
00469       if (newmode == "idle")
00470       {
00471         state = ControlModeTypes::IDLE;
00472         info = "";
00473       }
00474       else if (newmode == "standby")
00475       {
00476         info = "";
00477         info_pub = nh_priv.advertise<control_mode_hover_info> ("info", 10);
00478         state = ControlModeTypes::STANDBY;
00479       }
00480       else if (newmode == "active")
00481       {
00482         if (state == ControlModeTypes::STANDBY)
00483         {
00484           state = ControlModeTypes::ACTIVE;
00485           double current_yaw, current_pitch, current_roll;
00486           double current_x, current_y, current_z;
00487           odom_msg_to_ypr(boost::make_shared<nav_msgs::Odometry>(latest_state), current_yaw, current_pitch,
00488                           current_roll);
00489           odom_msg_to_xyz(boost::make_shared<nav_msgs::Odometry>(latest_state), current_x, current_y, current_z);
00490           hover_point point_here;
00491           point_here.yaw = to_degrees(current_yaw);
00492           point_here.north = current_x;
00493           point_here.east = current_y;
00494           point_here.east_vel = 0;
00495           point_here.north_vel = 0;
00496           point_here.name = "_hover_mode_entry";
00497           set_hover_point(point_here, true);
00498           alt_override = 9999;
00499           info = "";
00500         }
00501       }
00502       else
00503       {
00504         NODELET_ERROR("Unknown mode");
00505       }
00506     }
00507     else
00508     {
00509       NODELET_ERROR("Invalid command");
00510     }
00511   }
00512 
00513   void parse_define_hover_point(const vector<string> &words)
00514   {
00515     /*
00516      * Examples:
00517      * a) Define a named point 'foo' with north = 0.1 m, east = 0.2 m, yaw and velocities unspecified.
00518      *          define hover_point foo 0.1 0.2
00519      *
00520      * b) Define a named point 'bar' with north = 0.1 m, east = 0.2 m, yaw = 45 deg and velocities unspecified.
00521      *          define hover_point bar 0.1 0.2 45.0
00522      *
00523      */
00524     int nw = words.size();
00525     if (not ((nw == 5) or (nw == 7) or (nw == 8)))
00526     {
00527       NODELET_ERROR("Invalid command");
00528     }
00529     else
00530     {
00531       string point_name = words[2];
00532       if (hover_point_exists(point_name))
00533       {
00534         NODELET_WARN_STREAM("hover_point '" << point_name << "' already exists and will be redefined");
00535       }
00536       hover_points[point_name].name = point_name;
00537       double north = atof(words[3].c_str());
00538       double east = atof(words[4].c_str());
00539       if (not hover_point_within_bounds(north, east))
00540         NODELET_WARN_STREAM("Hover point " << point_name << " has out-of-bounds coordinates. Point will be defined but cannot be used.");
00541       hover_points[point_name].north = north;
00542       hover_points[point_name].east = east;
00543       if ((nw == 7) or (nw == 8)) // north_vel, east_vel and perhaps yaw_coord specified:
00544 
00545       {
00546         hover_points[point_name].north_vel = atof(words[5].c_str());
00547         hover_points[point_name].east_vel = atof(words[6].c_str());
00548         if (nw == 7)
00549         {
00550           hover_points[point_name].yaw = NAN;
00551           NODELET_DEBUG_STREAM(
00552                                "New hover_point defined: name='" << point_name << "' north="
00553                                    << hover_points[point_name].north << " east=" << hover_points[point_name].east
00554                                    << " north_vel=" << hover_points[point_name].north_vel << " east_vel="
00555                                    << hover_points[point_name].east_vel << ". Yaw unspecified.");
00556         }
00557         else if (nw == 8)
00558         {
00559           hover_points[point_name].yaw = atof(words[7].c_str());
00560           NODELET_DEBUG_STREAM(
00561                                "New hover_point defined: name='" << point_name << "' north="
00562                                    << hover_points[point_name].north << " east=" << hover_points[point_name].east
00563                                    << " north_vel=" << hover_points[point_name].north_vel << " east_vel="
00564                                    << hover_points[point_name].east_vel << " yaw=" << hover_points[point_name].yaw);
00565         }
00566       }
00567       else
00568       {
00569         hover_points[point_name].north_vel = 0;
00570         hover_points[point_name].east_vel = 0;
00571         hover_points[point_name].yaw = NAN;
00572         NODELET_DEBUG_STREAM(
00573                              "New hover_point defined: name='" << point_name << "' north="
00574                                  << hover_points[point_name].north << " east=" << hover_points[point_name].east
00575                                  << " north_vel=" << hover_points[point_name].north_vel << " east_vel="
00576                                  << hover_points[point_name].east_vel << ". Yaw unspecified.");
00577       }
00578     }
00579   }
00580 
00581 protected:
00582   bool hover_point_within_bounds(const double north, const double east)
00583   {
00584     return ((north >= north_cmd_min) and (north <= north_cmd_max) //
00585         and (east >= east_cmd_min) and (east <= east_cmd_max));
00586   }
00587 
00588   bool hover_point_exists(const string point_name)
00589   {
00590     map<string, hover_point>::iterator it;
00591     it = hover_points.find(point_name);
00592     return (not (it == hover_points.end()));
00593   }
00594 
00595   void set_gains(double KP, double KI, double KD, double Ilimit)
00596   {
00597     north_pid.initPid(KP, KI, KD, Ilimit, -Ilimit);
00598     east_pid.initPid(KP, KI, KD, Ilimit, -Ilimit);
00599   }
00600 
00601   // syntax:
00602   // set gains KP KI KD Ilimit
00603   void parse_set_gains(const vector<string> &words)
00604   {
00605     int nw = words.size();
00606     if (nw == 6)
00607     {
00608       double KP_new = atof(words[2].c_str());
00609       double KI_new = atof(words[3].c_str());
00610       double KD_new = atof(words[4].c_str());
00611       double Ilimit_new = atof(words[5].c_str());
00612       // TODO: do some checks on what was entered
00613       KP = KP_new;
00614       KI = KI_new;
00615       KD = KD_new;
00616       Ilimit = Ilimit_new;
00617       set_gains(KP, KI, KD, Ilimit);
00618       NODELET_INFO("Set new gains: KP=%f, KI=%f, KD=%f, Ilimit=%f", KP, KI, KD, Ilimit);
00619     }
00620     else
00621     {
00622       NODELET_ERROR("Invalid command");
00623     }
00624   }
00625 
00626   void parse_set_hover_point(const vector<string> &words)
00627   {
00628     int nw = words.size();
00629     if (nw == 3)
00630     {
00631       string point_name = words[2];
00632       if (hover_point_exists(point_name))
00633       {
00634         set_hover_point(hover_points[point_name]);
00635       }
00636       else
00637       {
00638         NODELET_ERROR("Invalid hover_point name");
00639       }
00640     }
00641     else
00642     {
00643       NODELET_ERROR("Invalid command");
00644     }
00645   }
00646 
00647   void set_hover_point(const hover_point& point, bool reset = false)
00648   {
00649     if (hover_point_within_bounds(point.north, point.east))
00650     {
00651       north_cmd = point.north;
00652       east_cmd = point.east;
00653       north_vel_cmd = point.north_vel;
00654       east_vel_cmd = point.east_vel;
00655       if (reset)
00656       {
00657         north_pid.reset();
00658         east_pid.reset();
00659       }
00660       current_hover_point = point;
00661       //    NODELET_INFO_STREAM("Setting hover setpoint to hover_point '" << point.name << "': north="
00662       //        << north_cmd << " east=" << east_cmd
00663       //        << " north_vel_cmd=" << north_vel_cmd << " east_vel_cmd=" << east_vel_cmd);
00664       if (not isnan(point.yaw))
00665       {
00666         yaw_cmd = point.yaw;
00667         //      NODELET_INFO_STREAM("Setting yaw setpoint to " << yaw_cmd);
00668       }
00669       else
00670       {
00671         //      NODELET_INFO("Hover point does not define a yaw value, yaw command unmodified.");
00672       }
00673       //    send_viz_marker(north_cmd, east_cmd, yaw_cmd);
00674     }
00675     else
00676     {
00677       NODELET_ERROR("Cannot set hover point to %f, %f (out of bounds)", point.north, point.east);
00678     }
00679   }
00680 
00681 };
00682 
00683 }


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