control_mode.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" // This class' header
00035 #include "flyer_controller/control_modes.h" // srv
00036 //using namespace flyer_controller;
00037 namespace flyer_controller
00038 {
00039 
00040 std::string ControlMode::stateToString(ControlModeTypes::ControlModeState t)
00041 {
00042   switch (t)
00043   {
00044     case ControlModeTypes::OFF:
00045       return "OFF";
00046     case ControlModeTypes::ERROR:
00047       return "ERROR";
00048     case ControlModeTypes::IDLE:
00049       return "IDLE";
00050     case ControlModeTypes::STANDBY:
00051       return "STANDBY";
00052     case ControlModeTypes::ACTIVE:
00053       return "ACTIVE";
00054   }
00055   return "Unknown";
00056 }
00057 
00058 void ControlMode::onInit()
00059 {
00060   NODELET_INFO("ControlMode onInit() called");
00061   nh = getNodeHandle();
00062   nh_priv = getPrivateNodeHandle();
00063 
00064   // Diagnostics
00065   diag_updater.add(getName() + " status", this, &ControlMode::diagnostics);
00066   diag_updater.setHardwareID("none");
00067   diag_updater.force_update();
00068 
00069   // Parameters
00070   nh_priv.param("status_report_rate", status_report_rate, status_report_rate);
00071   nh_priv.param("control_output_rate", control_output_rate, control_output_rate);
00072   nh_priv.param("event_driven", event_driven, event_driven);
00073   CHECK_PARAMETER((status_report_rate > 0), "parameter value out of range");
00074   CHECK_PARAMETER((control_output_rate > 0), "parameter value out of range");
00075 
00076   // Publishers
00077   control_mode_status_pub = nh_priv.advertise<control_mode_status> ("status", 1, true);
00078 }
00079 
00080 ControlMode::ControlMode() :
00081   status_report_rate(5), control_output_rate(10),
00082       event_driven(false), //
00083       state(ControlModeTypes::OFF), ready(false), got_first_state(false), seen_max_alt(false), seen_min_alt(false),
00084       got_first_joy(false), latest_alt_cmd(0), state_updated(false), state_count(0), control_count(0)
00085 {
00086 }
00087 
00089 void ControlMode::diagnostics(diagnostic_updater::DiagnosticStatusWrapper& stat)
00090 {
00091   int status;
00092   status = ((state != ControlModeTypes::ERROR) ? diagnostic_msgs::DiagnosticStatus::OK
00093       : diagnostic_msgs::DiagnosticStatus::ERROR);
00094   stat.summary(status, stateToString(state));
00095   stat.add("ready", ready);
00096   stat.add("info", info);
00097   stat.add("state_count", state_count);
00098   stat.add("control_count", control_count);
00099 }
00100 
00101 void ControlMode::requestRegistration(const std::string& mode_name, double wait_time)
00102 {
00103   reg_timer = nh.createTimer(ros::Duration(0.01),
00104                              boost::bind(&ControlMode::requestRegistration2, this, _1, mode_name, wait_time), true);
00105 }
00106 
00107 void ControlMode::requestRegistration2(const ros::TimerEvent& event, const std::string& mode_name, double wait_time)
00108 {
00109   // Service Client
00110   NODELET_INFO("Waiting %f seconds before trying to register..", wait_time);
00111   ros::Duration d(wait_time);
00112   d.sleep();
00113   NODELET_INFO("Waiting for controller/control_modes service...");
00114   info = "Waiting for controller/control_mode service...";
00115   ros::service::waitForService("controller/control_modes"); // blocks until service available, no timeout
00116   info = "registering service...";
00117   control_modes register_service;
00118   register_service.request.request = "register " + mode_name + " " + getName(); //ros::this_node::getName();
00119   bool registered = ros::service::call("controller/control_modes", register_service);
00120   if (registered)
00121   {
00122     if (register_service.response.response == "success")
00123     {
00124       NODELET_INFO_STREAM("Successfully registered control mode " << mode_name);
00125       info = "control mode registered";
00126       startDataFlow();
00127     }
00128     else
00129     {
00130       NODELET_ERROR_STREAM ("Control mode registration failed, response: '" << register_service.response.response
00131           << "', reason: '" << register_service.response.reason << "'");
00132       state = ControlModeTypes::ERROR;
00133       info = "registration failed";
00134     }
00135   }
00136   else
00137   {
00138     NODELET_ERROR("Control mode registration service call failed");
00139     state = ControlModeTypes::ERROR;
00140     info = "registration service call failed";
00141   }
00142 }
00143 
00144 ControlMode::~ControlMode()
00145 {
00146   NODELET_INFO("Destructor called");
00147 }
00148 
00149 void ControlMode::startDataFlow()
00150 {
00151   //NODELET_INFO("Setting up publishers, subscribers, and timers..");
00152   // Publishers
00153   output_pub = nh_priv.advertise<control_mode_output> ("output", 10);
00154   // Subscribers
00155   control_mode_cmd_sub = nh_priv.subscribe("cmd", 500, &ControlMode::controlModeCmdCallback, this);
00156   opercmd_sub = nh.subscribe("teleop_flyer/operator_cmds", 10, &ControlMode::operCmdCallback, this);
00157   state_sub = nh.subscribe("odom", 2, &ControlMode::stateCallback, this);
00158   // Timers
00159   if (not event_driven)
00160     output_controls_timer = nh.createTimer(ros::Duration(1 / control_output_rate),
00161                                            &ControlMode::outputControlTimerCallback, this);
00162   report_status_timer = nh.createTimer(ros::Duration(1 / status_report_rate), &ControlMode::reportStatusTimerCallback,
00163                                        this);
00164 
00165   state = ControlModeTypes::IDLE;
00166   info = "data flow started";
00167 
00168 }
00169 
00170 void ControlMode::controlModeCmdCallback(const control_mode_cmdConstPtr& msg)
00171 {
00172   NODELET_DEBUG_STREAM("Heard command: " << msg->cmd);
00173   if (msg->cmd == "mode idle")
00174   {
00175     state = ControlModeTypes::IDLE;
00176     info = "";
00177   }
00178   else if (msg->cmd == "mode standby")
00179   {
00180     state = ControlModeTypes::STANDBY;
00181     info = "";
00182   }
00183   else if (msg->cmd == "mode active")
00184   {
00185     if (state == ControlModeTypes::STANDBY)
00186     {
00187       state = ControlModeTypes::ACTIVE;
00188       info = "";
00189     }
00190     else
00191     {
00192       NODELET_ERROR("Invalid transition");
00193     }
00194   }
00195   else
00196   {
00197     NODELET_ERROR_STREAM("Command unknown: " << msg->cmd);
00198   }
00199 }
00200 
00201 void ControlMode::operCmdCallback(const starmac_msgs::OperatorCommandsConstPtr& msg)
00202 {
00203   //NODELET_DEBUG_STREAM(__PRETTY_FUNCTION__ << " callback called");
00204   latest_opercmd = *msg;
00205   if (not got_first_joy)
00206     got_first_joy = true;
00207 }
00208 
00209 void ControlMode::stateCallback(const nav_msgs::OdometryConstPtr& msg)
00210 {
00211   //NODELET_DEBUG_STREAM(__PRETTY_FUNCTION__ << " callback called");
00212   if (!got_first_state)
00213     got_first_state = true;
00214   latest_state = *msg;
00215   state_updated = true;
00216   state_count++;
00217   if (event_driven)
00218   {
00219     control_count++;
00220     outputControl();
00221   }
00222   //NODELET_INFO_STREAM("Got state, z = " << latest_state.pose.pose.position.z);
00223 }
00224 
00225 void ControlMode::reportStatusTimerCallback(const ros::TimerEvent& e)
00226 {
00227   control_mode_statusPtr msg(new control_mode_status);
00228   //NODELET_INFO_STREAM(__PRETTY_FUNCTION__);
00229   msg->state = state;
00230   msg->info = info;
00231   msg->ready = ready;
00232   control_mode_status_pub.publish(msg);
00233   diag_updater.update();
00234 }
00235 
00236 void ControlMode::outputControlTimerCallback(const ros::TimerEvent& e)
00237 {
00238   //NODELET_INFO_STREAM(__PRETTY_FUNCTION__);
00239   if (not event_driven)
00240   {
00241     control_count++;
00242     outputControl();
00243   }
00244   else
00245     ROS_FATAL("Code should not get here! Do some debugging!");
00246 }
00247 
00248 void ControlMode::outputControl()
00249 {
00250   control_mode_outputPtr control_out(new control_mode_output);
00251   switch (state)
00252   {
00253     case ControlModeTypes::STANDBY:
00254     case ControlModeTypes::ACTIVE:
00255       output_pub.publish(control_out);
00256       break;
00257     default:
00258       break;
00259   }
00260 
00261 }
00262 
00263 }// namespace
00264 


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