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/control_modes.h" 
00036 
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   
00065   diag_updater.add(getName() + " status", this, &ControlMode::diagnostics);
00066   diag_updater.setHardwareID("none");
00067   diag_updater.force_update();
00068 
00069   
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   
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   
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"); 
00116   info = "registering service...";
00117   control_modes register_service;
00118   register_service.request.request = "register " + mode_name + " " + 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   
00152   
00153   output_pub = nh_priv.advertise<control_mode_output> ("output", 10);
00154   
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   
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   
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   
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   
00223 }
00224 
00225 void ControlMode::reportStatusTimerCallback(const ros::TimerEvent& e)
00226 {
00227   control_mode_statusPtr msg(new control_mode_status);
00228   
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   
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 }
00264