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 <ros/ros.h>
00035 #include <nodelet/nodelet.h>
00036 #include <pluginlib/class_list_macros.h>
00037 #include <diagnostic_updater/diagnostic_updater.h>
00038 #include <map>
00039 #include <string>
00040 #include <set>
00041 #include <algorithm>
00042 #include "topic_tools/MuxAdd.h"
00043 #include "topic_tools/MuxSelect.h"
00044 #include "topic_tools/MuxList.h"
00045
00046 #include "flyer_controller/control_modes.h"
00047 #include "flyer_controller/control_mode_cmd.h"
00048 #include "flyer_controller/control_mode_status.h"
00049 #include "flyer_controller/controller_status.h"
00050 #include "flyer_controller/controller_cmd.h"
00051 #include <boost/algorithm/string.hpp>
00052
00053 using namespace std;
00054
00055 namespace flyer_controller
00056 {
00057
00058 namespace ControllerTypes
00059 {
00060 enum ControllerStates
00061 {
00062 ERROR = 0, OFF = 1, INITIALIZE = 2, STANDBY = 3, OPERATIONAL = 4
00063 };
00064 typedef ControllerStates ControllerState;
00065
00066 }
00067
00068 using namespace ControllerTypes;
00069
00070 class Controller : public nodelet::Nodelet
00071 {
00072 private:
00073 ros::NodeHandle nh;
00074 ros::NodeHandle nh_priv;
00075
00076 string initial_active_mode;
00077 string initial_standby_mode;
00078 double mainloop_rate;
00079
00080 ros::Publisher status_pub;
00081 map<string, ros::Publisher> mode_cmd_pubs;
00082
00083 ros::Subscriber cmd_sub;
00084 map<string, ros::Subscriber> mode_status_subs;
00085
00086 ros::Timer mainloop_timer;
00087
00088 diagnostic_updater::Updater diag_updater;
00089
00090
00091 ros::ServiceServer control_modes_service;
00092
00093 string current_mode;
00094 string standby_mode;
00095 set<string> registered_modes;
00096 map<string, string> node_mode_map;
00097 map<string, string> mode_node_map;
00098 map<string, control_mode_status> latest_mode_status;
00099 ControllerState state;
00100 string info;
00101 bool command_pending;
00102 string pending_command;
00103 boost::mutex mainloop_mutex;
00104 boost::mutex register_mutex;
00105
00106
00107 public:
00108 Controller() :
00109 initial_active_mode("idle"), initial_standby_mode("attitude"), mainloop_rate(5.0), diag_updater(), state(OFF),
00110 info(""), command_pending(false), pending_command("")
00111 {
00112 }
00113
00114 void onInit()
00115 {
00116
00117 nh = getMTNodeHandle();
00118 nh_priv = getMTPrivateNodeHandle();
00119
00120 NODELET_INFO("controller.cpp onInit() begin");
00121
00122
00123 diag_updater.add("Controller Status", this, &Controller::diagnostics);
00124 diag_updater.setHardwareID("none");
00125 diag_updater.force_update();
00126
00127 nh_priv.param("initial_active_mode", initial_active_mode, initial_active_mode);
00128 nh_priv.param("initial_standby_mode", initial_standby_mode, initial_standby_mode);
00129 nh_priv.param("mainloop_rate", mainloop_rate, mainloop_rate);
00130
00131 status_pub = nh_priv.advertise<controller_status> ("status", 1, true);
00132
00133 cmd_sub = nh_priv.subscribe("cmd", 10, &Controller::commandCallback, this);
00134
00135 control_modes_service = nh_priv.advertiseService("control_modes", &Controller::controlModesServiceCallback, this);
00136
00137
00138 mainloop_timer = nh.createTimer(ros::Duration(1 / mainloop_rate), &Controller::mainLoopCallback, this);
00139
00140 state = INITIALIZE;
00141
00142 NODELET_INFO("controller.cpp onInit() done");
00143
00144 }
00145
00146 std::string stateToString(ControllerTypes::ControllerState t)
00147 {
00148 switch (t)
00149 {
00150 case ControllerTypes::OFF:
00151 return "OFF";
00152 case ControllerTypes::ERROR:
00153 return "ERROR";
00154 case ControllerTypes::INITIALIZE:
00155 return "INITIALIZE";
00156 case ControllerTypes::STANDBY:
00157 return "STANDBY";
00158 case ControllerTypes::OPERATIONAL:
00159 return "OPERATIONAL";
00160 }
00161 return "Unknown";
00162 }
00163
00164 private:
00165
00166 void diagnostics(diagnostic_updater::DiagnosticStatusWrapper& stat)
00167 {
00168 int status;
00169 status = ((state != ERROR) ? diagnostic_msgs::DiagnosticStatus::OK : diagnostic_msgs::DiagnosticStatus::ERROR);
00170 stat.summary(status, stateToString(state));
00171 stat.add("info", info);
00172 stat.add("registered modes", registered_modes.size());
00173 stat.add("current mode", current_mode);
00174 stat.add("standby mode", standby_mode);
00175 }
00176
00177 void commandCallback(const controller_cmdConstPtr& msg)
00178 {
00179
00180
00181 ROS_INFO_STREAM("Command received: " << msg->cmd);
00182 if (command_pending)
00183 {
00184 ROS_ERROR("Command already pending - new command ignored");
00185 }
00186 else
00187 {
00188 command_pending = true;
00189 pending_command = msg->cmd;
00190 }
00191 }
00192
00193 bool controlModesServiceCallback(control_modes::Request& request, control_modes::Response& response)
00194 {
00195 boost::mutex::scoped_lock lock(register_mutex);
00196 ROS_INFO_STREAM("Service call received. Request was: " << request.request);
00197 vector<string> words;
00198 boost::split(words, request.request, boost::is_any_of(" "));
00199
00200 if (words.size() > 0)
00201 {
00202 if (words[0] == "register")
00203 {
00204 if (words.size() != 3)
00205 {
00206 ROS_ERROR("Invalid request");
00207 response.response = "failure";
00208 response.reason = "invalid number of parameters";
00209 }
00210 else
00211 {
00212 string mode_name = words[1];
00213 string mode_node = words[2];
00214 if (registered_modes.count(mode_name) > 0)
00215 {
00216 ROS_ERROR_STREAM("A control mode named " << mode_name << " has already been registered.");
00217 response.response = "failure";
00218 response.reason = "control mode already registered";
00219 }
00220 else
00221 {
00222 ROS_INFO_STREAM("Registering control mode, name: " << mode_name << ", node: " << mode_node);
00223 mode_cmd_pubs[mode_name] = nh.advertise<control_mode_cmd> (mode_node + "/cmd", 1, true);
00224
00225
00226
00227 mode_status_subs[mode_name]
00228 = nh.subscribe<control_mode_status> (
00229 mode_node + "/status",
00230 10,
00231 boost::bind(&Controller::controlModesStatusCallback, this, _1,
00232 mode_node));
00233 registered_modes.insert(mode_name);
00234 node_mode_map[nh.resolveName(mode_node)] = mode_name;
00235 mode_node_map[mode_name] = nh.resolveName(mode_node);
00236 response.response = "success";
00237 }
00238 }
00239 }
00240 }
00241 else
00242 {
00243 response.response = "failure";
00244 response.reason = "invalid request";
00245 }
00246 ROS_INFO_STREAM("Completed service call. Request was: " << request.request);
00247
00248 return true;
00249 }
00250
00251 void controlModesStatusCallback(const flyer_controller::control_mode_statusConstPtr& msg, string source)
00252 {
00253
00254
00255
00256 latest_mode_status[node_mode_map[source]] = *msg;
00257 }
00258
00259 void mainLoopCallback(const ros::TimerEvent& e)
00260 {
00261 boost::mutex::scoped_lock lock(mainloop_mutex);
00262
00263 diag_updater.update();
00264
00265 switch (state)
00266 {
00267 case ERROR:
00268 break;
00269 case OFF:
00270 break;
00271 case INITIALIZE:
00272 execute_INITIALIZE();
00273 break;
00274 case STANDBY:
00275 execute_STANDBY();
00276 break;
00277 case OPERATIONAL:
00278 execute_OPERATIONAL();
00279 break;
00280 default:
00281 break;
00282 }
00283 controller_statusPtr status_msg(new controller_status);
00284 status_msg->state = state;
00285 status_msg->info = info;
00286 status_msg->active_mode = current_mode;
00287 status_msg->header.stamp = e.current_real;
00288 map<string, control_mode_status>::iterator it;
00289 getStandbyModes(status_msg->standby_modes);
00290 status_pub.publish(status_msg);
00291 }
00292
00293 void getStandbyModes(vector<string>& modes)
00294 {
00295 map<string, control_mode_status>::iterator it;
00296 modes.clear();
00297 for (it = latest_mode_status.begin(); it != latest_mode_status.end(); it++)
00298 {
00299 if ((*it).second.state == control_mode_status::STATE_STANDBY)
00300 {
00301 modes.push_back((*it).first);
00302 }
00303 }
00304
00305 }
00306
00307 void execute_INITIALIZE()
00308 {
00309
00310
00311 static bool initialize_waiting_modes_mux = true, initialize_transitioned_active_mode = false,
00312 initialize_transitioned_standby_mode = false, initialize_active_mode_in_standby = false,
00313 initialize_standby_mode_in_standby = false, initialize_active_muxed = false, initialize_standby_muxed =
00314 false;
00315 enum InitializePhases
00316 {
00317 INITIALIZE_WAIT_MODES_MUX, INITIALIZE_TRANSITION_ACTIVE, INITIALIZE_TRANSITION_STANDBY,
00318 INITIALIZE_WAIT_STANDBY_TALKBACK
00319 };
00320
00321 static InitializePhases init_phase = INITIALIZE_WAIT_MODES_MUX;
00322
00323
00324 switch (init_phase)
00325 {
00326 case INITIALIZE_WAIT_MODES_MUX:
00327 {
00328
00329 }
00330 break;
00331 }
00332
00333 if (initialize_waiting_modes_mux)
00334 {
00335 if (registered_modes.count(initial_active_mode) > 0 && registered_modes.count(initial_standby_mode) > 0
00336 && ros::service::exists("controller_mux/add", false))
00337 {
00338 ROS_INFO("Initial modes have registered");
00339 info = "got modes and mux";
00340 diag_updater.force_update();
00341 initialize_waiting_modes_mux = false;
00342 }
00343 else
00344 {
00345 info = "waiting for modes and mux";
00346 }
00347 }
00348 else
00349 {
00350 topic_tools::MuxAdd mux_add_srv;
00351 if (!initialize_transitioned_active_mode)
00352 {
00353 control_mode_cmdPtr active_to_standby_msg(new control_mode_cmd);
00354 active_to_standby_msg->cmd = "mode standby";
00355 mode_cmd_pubs[initial_active_mode].publish(active_to_standby_msg);
00356 initialize_transitioned_active_mode = true;
00357 }
00358 else
00359 {
00360 if (!initialize_active_muxed)
00361 {
00362 mux_add_srv.request.topic = "control_mode_" + initial_active_mode + "/output";
00363 if (ros::service::call("controller_mux/add", mux_add_srv))
00364 {
00365 initialize_active_muxed = true;
00366 }
00367 }
00368 }
00369 if (!initialize_transitioned_standby_mode)
00370 {
00371 control_mode_cmdPtr standby_to_standby_msg(new control_mode_cmd);
00372 standby_to_standby_msg->cmd = "mode standby";
00373 mode_cmd_pubs[initial_standby_mode].publish(standby_to_standby_msg);
00374 initialize_transitioned_standby_mode = true;
00375 }
00376 else
00377 {
00378 if (!initialize_standby_muxed)
00379 {
00380 mux_add_srv.request.topic = "control_mode_" + initial_standby_mode + "/output";
00381 if (ros::service::call("controller_mux/add", mux_add_srv))
00382 {
00383 initialize_standby_muxed = true;
00384 }
00385 }
00386 }
00387 if (initialize_transitioned_active_mode && initialize_active_muxed && initialize_transitioned_standby_mode
00388 && initialize_standby_muxed)
00389 {
00390 info = "waiting for STANDBY talkback";
00391
00392 if (latest_mode_status[initial_active_mode].state == control_mode_status::STATE_STANDBY
00393 && latest_mode_status[initial_standby_mode].state == control_mode_status::STATE_STANDBY)
00394 {
00395 ROS_INFO_STREAM("Initial active and standby modes reporting STANDBY state, controller going to STANDBY");
00396 state = STANDBY;
00397 info = "";
00398 current_mode = initial_active_mode;
00399 standby_mode = initial_standby_mode;
00400 diag_updater.force_update();
00401 }
00402 }
00403 }
00404 }
00405
00406 void execute_STANDBY()
00407 {
00408
00409
00410
00411
00412
00413
00414
00415
00416 static bool standby_entering_operational = false, standby_commanded_active_mode = false,
00417 standby_mux_selected_active = false;
00418
00419
00420 if (command_pending)
00421 {
00422 if (pending_command == "mode operational" and !standby_entering_operational)
00423 {
00424 ROS_INFO("Entering OPERATIONAL");
00425 command_pending = false;
00426 pending_command = "";
00427 info = "entering OPERATIONAL";
00428 diag_updater.force_update();
00429 standby_entering_operational = true;
00430 }
00431 else
00432 {
00433 ROS_ERROR("Invalid command in STANDBY mode");
00434 command_pending = false;
00435 pending_command = "";
00436 }
00437 }
00438 if (standby_entering_operational)
00439 {
00440 if (!standby_commanded_active_mode)
00441 {
00442
00443 control_mode_cmdPtr current_to_active_msg(new control_mode_cmd);
00444 current_to_active_msg->cmd = "mode active";
00445 mode_cmd_pubs[current_mode].publish(current_to_active_msg);
00446 standby_commanded_active_mode = true;
00447 info = "commanded current mode to ACTIVE";
00448 }
00449 else
00450 {
00451 if (!standby_mux_selected_active)
00452 {
00453 topic_tools::MuxSelect mux_sel_srv;
00454 mux_sel_srv.request.topic = mode_node_map[current_mode] + "/output";
00455 ros::service::call("controller_mux/select", mux_sel_srv);
00456 standby_mux_selected_active = true;
00457 info = "requested mux select: " + mode_node_map[current_mode] + "/output";
00458 }
00459 else
00460 {
00461
00462 }
00463
00464 if (latest_mode_status[current_mode].state == control_mode_status::STATE_ACTIVE)
00465 {
00466 state = OPERATIONAL;
00467 info = "current mode reporting ACTIVE";
00468 diag_updater.force_update();
00469 }
00470 }
00471 }
00472 }
00473
00474 enum OPERATIONAL_Substate
00475 {
00476 OP_READY, OP_ACTIVATING_MODE, OP_STANDBYING_MODE
00477 };
00478
00479 void execute_OPERATIONAL()
00480 {
00481
00482
00483
00484
00485
00486
00487
00488
00489 static OPERATIONAL_Substate substate = OP_READY;
00490 static OPERATIONAL_Substate prev_substate = OP_READY;
00491 bool reset = true;
00492 string new_mode = "";
00493
00494 if (substate == OP_READY)
00495 {
00496 execute_OPERATIONAL_READY(substate, new_mode);
00497 }
00498 if (substate != prev_substate)
00499 {
00500 ROS_DEBUG_STREAM("Operational substate changed: " << prev_substate << " -> " << substate);
00501 reset = true;
00502 }
00503 else
00504 {
00505 reset = false;
00506 }
00507
00508 prev_substate = substate;
00509
00510 bool substate_completed = false;
00511 switch (substate)
00512 {
00513 case OP_READY:
00514 break;
00515 case OP_ACTIVATING_MODE:
00516 substate_completed = execute_OPERATIONAL_ACTIVATING_MODE(reset, new_mode);
00517 break;
00518 case OP_STANDBYING_MODE:
00519 substate_completed = execute_OPERATIONAL_STANDBYING_MODE(reset, new_mode);
00520 break;
00521 }
00522 if (substate_completed)
00523 {
00524 substate = OP_READY;
00525 }
00526
00527 }
00528
00529 void execute_OPERATIONAL_READY(OPERATIONAL_Substate& substate, string& new_mode)
00530 {
00531
00532
00533
00534
00535 if (command_pending)
00536 {
00537 bool valid = false;
00538 string reason = "";
00539 vector<string> words;
00540 boost::split(words, pending_command, boost::is_any_of(" "));
00541 if (words.size() > 0)
00542 {
00543 if (words[0] == "control_mode")
00544
00545
00546
00547 {
00548 if (words.size() == 3)
00549 {
00550 if (words[1] == "to_active")
00551 {
00552 new_mode = words[2];
00553 if (new_mode == current_mode)
00554 {
00555 reason = ": current_mode already " + new_mode;
00556 }
00557 else
00558 {
00559 vector<string>::iterator it;
00560 vector<string> standby_modes;
00561 getStandbyModes(standby_modes);
00562 if (find(standby_modes.begin(), standby_modes.end(), new_mode) != standby_modes.end())
00563 {
00564 valid = true;
00565 info = "mode change accepted";
00566 substate = OP_ACTIVATING_MODE;
00567 }
00568 else
00569 {
00570 ROS_ERROR_STREAM("Mode " << new_mode << " is not in STANDBY, cannot activate");
00571 }
00572 }
00573 }
00574 else if (words[1] == "to_standby")
00575 {
00576 new_mode = words[2];
00577 valid = true;
00578 substate = OP_STANDBYING_MODE;
00579 }
00580 else if (words[1] == "to_idle")
00581 {
00582 ROS_ERROR("control_mode to_idle commands not yet implemented");
00583 }
00584 }
00585 }
00586 }
00587
00588 if (!valid)
00589 {
00590 ROS_ERROR_STREAM("Invalid command" << reason);
00591 info = "mode change rejected";
00592 }
00593
00594
00595 command_pending = false;
00596 pending_command = "";
00597 }
00598
00599 }
00600
00601 bool execute_OPERATIONAL_ACTIVATING_MODE(bool reset, const string mode_to_activate)
00602 {
00603 enum SequenceStatus
00604 {
00605 MODE_CHANGE_ACCEPTED, WAITING_NEW_ACTIVE_TALKBACK, WAITING_OLD_STANDBY_TALKBACK, FINISHED
00606 };
00607 static SequenceStatus sequence_status = FINISHED;
00608 static string new_mode;
00609 ROS_DEBUG_STREAM(
00610 "execute_OPERATIONAL_ACTIVATING_MODE, reset=" << reset << ", new_mode=" << new_mode
00611 << ", sequence_status=" << sequence_status);
00612 if (reset)
00613 {
00614 sequence_status = MODE_CHANGE_ACCEPTED;
00615 new_mode = mode_to_activate;
00616 }
00617
00618 switch (sequence_status)
00619 {
00620 case MODE_CHANGE_ACCEPTED:
00621 {
00622 if (latest_mode_status[new_mode].ready)
00623 {
00624
00625 topic_tools::MuxSelect mux_sel_srv;
00626 mux_sel_srv.request.topic = mode_node_map[new_mode] + "/output";
00627 ros::service::call("controller_mux/select", mux_sel_srv);
00628
00629 control_mode_cmdPtr new_to_active_msg(new control_mode_cmd);
00630 new_to_active_msg->cmd = "mode active";
00631 mode_cmd_pubs[new_mode].publish(new_to_active_msg);
00632 info = "mux selected and commanded current mode to ACTIVE - waiting to see ACTIVE";
00633 sequence_status = WAITING_NEW_ACTIVE_TALKBACK;
00634 }
00635 else
00636 {
00637 ROS_ERROR_STREAM("mode " << new_mode << " reporting not ready to go ACTIVE, mode transition cancelled");
00638 info = "mode change failed -- see log";
00639 sequence_status = FINISHED;
00640 }
00641 }
00642 break;
00643 case WAITING_NEW_ACTIVE_TALKBACK:
00644 {
00645 if (latest_mode_status[new_mode].state == control_mode_status::STATE_ACTIVE)
00646 {
00647
00648 control_mode_cmdPtr old_to_standby_msg(new control_mode_cmd);
00649 old_to_standby_msg->cmd = "mode standby";
00650 mode_cmd_pubs[current_mode].publish(old_to_standby_msg);
00651 info = "commanded current mode to STANDBY - waiting to see STANDBY";
00652 sequence_status = WAITING_OLD_STANDBY_TALKBACK;
00653 }
00654 }
00655 break;
00656 case WAITING_OLD_STANDBY_TALKBACK:
00657 {
00658 if (latest_mode_status[current_mode].state == control_mode_status::STATE_STANDBY)
00659 {
00660 info = "old mode in STANDBY -- mode transition complete!";
00661 standby_mode = current_mode;
00662 current_mode = new_mode;
00663 sequence_status = FINISHED;
00664 }
00665 }
00666 break;
00667 case FINISHED:
00668 {
00669 ROS_ERROR("The code shouldn't get here--please debug!");
00670 }
00671 break;
00672 }
00673
00674 return (sequence_status == FINISHED);
00675 }
00676
00677 bool execute_OPERATIONAL_STANDBYING_MODE(bool reset, const string mode_to_standby)
00678 {
00679 enum SequenceStatus
00680 {
00681 MODE_CHANGE_ACCEPTED, WAITING_STANDBY_TALKBACK, ADDING_MUXER_INPUT, WAITING_MUXER_TALKBACK, FINISHED
00682 };
00683 static SequenceStatus sequence_status = FINISHED;
00684 static string new_mode;
00685 static int muxer_talkback_wait_cycles = 10;
00686
00687 ROS_DEBUG_STREAM(
00688 "execute_OPERATIONAL_STANDBYING_MODE, reset=" << reset << ", new_mode=" << new_mode
00689 << ", sequence_status=" << sequence_status);
00690 if (reset)
00691 {
00692 sequence_status = MODE_CHANGE_ACCEPTED;
00693 new_mode = mode_to_standby;
00694 muxer_talkback_wait_cycles = 10;
00695 }
00696
00697 switch (sequence_status)
00698 {
00699 case MODE_CHANGE_ACCEPTED:
00700 {
00701
00702 control_mode_cmdPtr new_to_standby_msg(new control_mode_cmd);
00703 new_to_standby_msg->cmd = "mode standby";
00704 mode_cmd_pubs[new_mode].publish(new_to_standby_msg);
00705 info = "mode " + new_mode + " commanded to STANDBY - waiting to see STANDBY";
00706 sequence_status = WAITING_STANDBY_TALKBACK;
00707 }
00708 break;
00709 case WAITING_STANDBY_TALKBACK:
00710 {
00711 if (latest_mode_status[new_mode].state == control_mode_status::STATE_STANDBY)
00712 {
00713 info = "mode in STANDBY - adding to muxer";
00714 sequence_status = ADDING_MUXER_INPUT;
00715 }
00716 }
00717 break;
00718 case ADDING_MUXER_INPUT:
00719 {
00720 topic_tools::MuxAdd mux_add_srv;
00721 mux_add_srv.request.topic = "control_mode_" + new_mode + "/output";
00722 ros::service::call("controller_mux/add", mux_add_srv);
00723 info = "waiting for muxer talkback...";
00724 sequence_status = WAITING_MUXER_TALKBACK;
00725 }
00726 break;
00727 case WAITING_MUXER_TALKBACK:
00728 {
00729 topic_tools::MuxList mux_list_srv;
00730 ros::service::call("controller_mux/list", mux_list_srv);
00731 vector<string>::iterator it;
00732 string full_topic_name = ros::names::resolve("control_mode_" + new_mode + "/output");
00733 if (find(mux_list_srv.response.topics.begin(), mux_list_srv.response.topics.end(), full_topic_name)
00734 != mux_list_srv.response.topics.end())
00735 {
00736 sequence_status = FINISHED;
00737 info = "muxer has " + full_topic_name + " in its input list - mode is in STANDBY";
00738 }
00739 else
00740 {
00741 muxer_talkback_wait_cycles--;
00742 }
00743 if (muxer_talkback_wait_cycles <= 0)
00744 {
00745 ROS_ERROR_STREAM(
00746 "Muxer still doesn't have topic " << full_topic_name << " after " << (10
00747 - muxer_talkback_wait_cycles) << "tries...");
00748 }
00749 }
00750 break;
00751 case FINISHED:
00752 {
00753 ROS_ERROR("The code shouldn't get here--please debug!");
00754 }
00755 break;
00756 }
00757
00758 return (sequence_status == FINISHED);
00759 }
00760
00761 };
00762 PLUGINLIB_DECLARE_CLASS(flyer_controller, Controller, flyer_controller::Controller, nodelet::Nodelet)
00763 ;
00764
00765 }
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775