00001 #include "cob_command_gui_rviz/command_gui_rviz_panel.h"
00002
00003 #include <wx/event.h>
00004 #include <XmlRpcValue.h>
00005
00006 namespace rviz
00007 {
00008
00009
00010 CommandGuiRvizPanel::CommandGuiRvizPanel(wxWindow *parent, const wxString& title):
00011 wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, title),
00012 planning_enabled(false),
00013 base_diff_enabled(false)
00014 {
00015
00016 if(false != Getparams())
00017 {
00018
00019 Creategui();
00020
00021
00022 action_client_ = new actionlib::SimpleActionClient<cob_script_server::ScriptAction>("cob_command_gui_rviz", true);
00023 }
00024 else
00025 {
00026
00027 statuslabel_ = new wxStaticText(this, wxID_ANY, wxT("\n\tstatus: Error! - parameter does not exist on ROS parameter server! \n\n"));
00028 }
00029 }
00030
00031
00032 CommandGuiRvizPanel::~CommandGuiRvizPanel()
00033 {
00034 }
00035
00036
00037 bool CommandGuiRvizPanel::Getparams()
00038 {
00039 std::string param_prefix = "/control_buttons";
00040
00041 if(false == (ros::param::has(param_prefix)))
00042 {
00043 ROS_DEBUG_ONCE("parameter '%s' does not exist on ROS parameter server, aborting...\n", param_prefix.c_str());
00044 return false;
00045 }
00046
00047 XmlRpc::XmlRpcValue group_param;
00048 ros::param::get(param_prefix, group_param);
00049
00050 XmlRpc::XmlRpcValue current_group;
00051 XmlRpc::XmlRpcValue buttons;
00052 XmlRpc::XmlRpcValue group_name;
00053 XmlRpc::XmlRpcValue component_name;
00054
00055 std::string groupkey = "groupx";
00056
00057
00058 for(int i = 0; i < group_param.size(); i++)
00059 {
00060 groupkey[5] = (i+'0'+1);
00061
00062 current_group = group_param[groupkey];
00063
00064 buttons = current_group["buttons"];
00065 group_name = current_group["group_name"];
00066 component_name = current_group["component_name"];
00067 static int id = 101;
00068
00069 Buttonlist current_buttons;
00070
00071
00072 for(int j=0; j < buttons.size(); j++)
00073 {
00074 if(buttons[j][1] == "move")
00075 {
00076 current_buttons.push_back(Descripe_button(id, buttons[j], component_name));
00077 }
00078 else if(buttons[j][1] == "move_base_rel")
00079 {
00080 current_buttons.push_back(Descripe_button(id, buttons[j], component_name));
00081 }
00082 else if(buttons[j][1] == "trigger")
00083 {
00084 current_buttons.push_back(Descripe_button(id, buttons[j], component_name));
00085
00086 if(buttons[j][2] == "stop")
00087 {
00088 stop_buttons_.push_back(component_name);
00089 }
00090 else if(buttons[j][2] == "init")
00091 {
00092 init_buttons_.push_back(component_name);
00093 }
00094 else if(buttons[j][2] == "recover")
00095 {
00096 recover_buttons_.push_back(component_name);
00097 }
00098
00099 }
00100 else if(buttons[j][1] == "stop")
00101 {
00102 current_buttons.push_back(Descripe_button(id, buttons[j], component_name));
00103 stop_buttons_.push_back(component_name);
00104 }
00105 else if(buttons[j][1] == "mode")
00106 {
00107 current_buttons.push_back(Descripe_button(id, buttons[j], component_name));
00108 }
00109 else
00110 {
00111 std::string fail = buttons[j][1];
00112 ROS_DEBUG_ONCE("function %s not known to rviz_movement_buttons panel", fail.c_str());
00113 }
00114
00115 id++;
00116 }
00117
00118
00119
00120
00121 if("base" == TostlString(component_name))
00122 {
00123 param_prefix = "/nav_buttons";
00124
00125 if(false != (ros::param::has(param_prefix)))
00126 {
00127 XmlRpc::XmlRpcValue nav_buttons_param;
00128 XmlRpc::XmlRpcValue nav_buttons;
00129
00130 ros::param::get(param_prefix, nav_buttons_param);
00131
00132 nav_buttons = nav_buttons_param["buttons"];
00133
00134 for(int k=0; k < nav_buttons.size(); k++)
00135 {
00136 current_buttons.push_back(Descripe_button(id, nav_buttons[k], component_name));
00137 id++;
00138 }
00139 }
00140 else
00141 {
00142 ROS_DEBUG_ONCE("parameter %s does not exist on ROS parameter server, no nav buttons will be available!\n", param_prefix.c_str());
00143 }
00144 }
00145
00146 groups_.push_back(std::pair<std::string, Buttonlist>(TostlString(group_name),current_buttons));
00147 }
00148
00149
00150 stop_buttons_.unique();
00151 init_buttons_.unique();
00152 recover_buttons_.unique();
00153
00154 return true;
00155 }
00156
00157
00158 void CommandGuiRvizPanel::Creategui()
00159 {
00160
00161 wxSizer *mainsizer = new wxBoxSizer(wxHORIZONTAL);
00162
00163
00164 sizers_.push_back(CreatesbGeneral());
00165
00166
00167 for(Grouplist::const_iterator group_ci = groups_.begin(); group_ci != groups_.end(); group_ci++)
00168 {
00169 wxSizer *vsizer = new wxStaticBoxSizer(wxVERTICAL, this, TowxString(group_ci->first));
00170
00171 for(Buttonlist::const_iterator button_ci = (group_ci->second).begin(); button_ci != (group_ci->second).end(); button_ci++)
00172 {
00173 vsizer->Add(AddButton(button_ci->id, TowxString(button_ci->button_name)), 0, wxEXPAND);
00174 }
00175
00176 sizers_.push_back(vsizer);
00177 }
00178
00179
00180 for(unsigned int i = 0; i < sizers_.size(); i++)
00181 {
00182 mainsizer->Add(sizers_[i], 1, wxEXPAND);
00183 }
00184
00185 mainsizer->SetSizeHints(this);
00186 this->SetSizerAndFit(mainsizer);
00187 }
00188
00189
00190 wxSizer* CommandGuiRvizPanel::CreatesbGeneral()
00191 {
00192
00193 const int genids[5] = {001, 002, 003, 004, 005};
00194
00195 wxSizer *vsizer = new wxStaticBoxSizer(wxVERTICAL, this, wxT("general"));
00196
00197 statuslabel_ = new wxStaticText(this, wxID_ANY, wxT("\n Status: OK"));
00198 cbPlanning_ = new wxCheckBox(this, genids[0], wxT("planning"));
00199 cbBaseDiff_ = new wxCheckBox(this, genids[1], wxT("base diff"));
00200
00201 wxButton *btnstopall = new wxButton(this, genids[2], wxT("stop all"), wxDefaultPosition, wxSize(30,29), wxBU_EXACTFIT);
00202 wxButton *btninitall = new wxButton(this, genids[3], wxT("init all"), wxDefaultPosition, wxSize(30,29), wxBU_EXACTFIT);
00203 wxButton *btnrecoverall = new wxButton(this, genids[4], wxT("recover all"), wxDefaultPosition, wxSize(30,29), wxBU_EXACTFIT);
00204
00205 btnstopall->Enable(true);
00206 btninitall->Enable(true);
00207 btnrecoverall->Enable(true);
00208
00209
00210 Connect(genids[0], wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(CommandGuiRvizPanel::planned_toggle));
00211 Connect(genids[1], wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(CommandGuiRvizPanel::base_mode_toggle));
00212
00213
00214 Connect(genids[2], wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(CommandGuiRvizPanel::OnStopAll));
00215 Connect(genids[3], wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(CommandGuiRvizPanel::OnInitAll));
00216 Connect(genids[4], wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(CommandGuiRvizPanel::OnRecoverAll));
00217
00218
00219 vsizer->Add(statuslabel_, 0, wxEXPAND);
00220 vsizer->Add(btnstopall, 0, wxEXPAND);
00221 vsizer->Add(btninitall, 0, wxEXPAND);
00222 vsizer->Add(btnrecoverall, 0, wxEXPAND);
00223
00224 vsizer->Add(cbPlanning_, 0, wxEXPAND);
00225 vsizer->Add(cbBaseDiff_, 0, wxEXPAND);
00226
00227 return vsizer;
00228 }
00229
00230
00231 Button_Description CommandGuiRvizPanel::Descripe_button(const int &id, XmlRpc::XmlRpcValue data, const std::string &component_name) const
00232 {
00233 Button_Description btn;
00234
00235 btn.id = id;
00236 btn.button_name = TostlString(data[0]);
00237 btn.function_name = TostlString(data[1]);
00238 btn.args.first = component_name;
00239 btn.args.second = TostlString(data[2]);
00240
00241 return btn;
00242 }
00243
00244
00245 wxButton* CommandGuiRvizPanel::AddButton(const int &id, const wxString &name)
00246 {
00247 wxButton *but = new wxButton(this, id, name, wxDefaultPosition, wxSize(30,29), wxBU_EXACTFIT, wxDefaultValidator, name);
00248
00249 but->Enable(true);
00250
00251 Connect(id, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(CommandGuiRvizPanel::OnClick));
00252
00253 return but;
00254 }
00255
00256
00257 void CommandGuiRvizPanel::OnClick(wxCommandEvent& event)
00258 {
00259 Button_Description pressed_button;
00260 std::string group_name;
00261
00262 pressed_button.id = event.GetId();
00263
00264
00265 for(Grouplist::const_iterator group_ci = groups_.begin(); group_ci != groups_.end(); group_ci++)
00266 {
00267 for(Buttonlist::const_iterator button_ci = group_ci->second.begin(); button_ci != group_ci->second.end(); button_ci++)
00268 {
00269 if((button_ci->id == pressed_button.id))
00270 {
00271 pressed_button.button_name = button_ci->button_name;
00272 pressed_button.function_name = button_ci->function_name;
00273 pressed_button.args = button_ci->args;
00274 group_name = group_ci->first;
00275 }
00276 }
00277 }
00278
00279 ROS_INFO("'%s-%s' clicked", group_name.c_str(), pressed_button.button_name.c_str());
00280
00281 cob_script_server::ScriptGoal goal;
00282 goal.function_name = pressed_button.function_name;
00283 goal.component_name = pressed_button.args.first;
00284 goal.parameter_name = pressed_button.args.second;
00285
00286 if("arm" == goal.component_name)
00287 {
00288 if(false != planning_enabled)
00289 {
00290 goal.mode = "planned";
00291 }
00292 }
00293
00294 if("base" == goal.component_name)
00295 {
00296 if(false != base_diff_enabled)
00297 {
00298 goal.mode = "diff";
00299 }
00300 }
00301
00302
00303 action_client_->sendGoal(goal);
00304 action_client_->waitForResult(ros::Duration(1.0));
00305 if(action_client_->getState() == actionlib::SimpleClientGoalState::SUCCEEDED)
00306 {
00307
00308 statuslabel_->SetLabel(wxT("\n Status: OK"));
00309
00310 this->GetSizer()->Layout();
00311 }
00312 else
00313 {
00314
00315 statuslabel_->SetLabel(wxT("\nstatus: \nno connect. to action server!\n\n"));
00316
00317 this->GetSizer()->Layout();
00318
00319 ROS_DEBUG_ONCE("Error! - no connection to action server!\n");
00320 }
00321
00322 ROS_INFO("current state: %s\n", action_client_->getState().toString().c_str());
00323 }
00324
00325
00326 void CommandGuiRvizPanel::OnStopAll(wxCommandEvent &event)
00327 {
00328 cob_script_server::ScriptGoal goal;
00329 bool success = true;
00330
00331 goal.function_name = "stop";
00332
00333 ROS_INFO("'stop all' clicked");
00334
00335 for(Stringlist::const_iterator ci = stop_buttons_.begin(); ci != stop_buttons_.end(); ci++)
00336 {
00337 goal.component_name = *ci;
00338
00339 action_client_->sendGoal(goal);
00340 action_client_->waitForResult(ros::Duration(1.0));
00341
00342 if("SUCCEEDED" != action_client_->getState().toString())
00343 {
00344 success = false;
00345 ROS_INFO("warning: component %s not properly stopped\n", goal.component_name.c_str());
00346 }
00347
00348 ROS_INFO("current state: %s\n", action_client_->getState().toString().c_str());
00349 }
00350
00351 if(false != success)
00352 {
00353 ROS_INFO("all components stopped\n");
00354
00355 statuslabel_->SetLabel(wxT("\n Status: OK"));
00356 this->GetSizer()->Layout();
00357 }
00358 else
00359 {
00360
00361 statuslabel_->SetLabel(wxT("\nstatus: \nno connect. to action server!\n\n"));
00362
00363 this->GetSizer()->Layout();
00364
00365 ROS_DEBUG_ONCE("Error! - no connection to action server!\n");
00366 }
00367 }
00368
00369
00370 void CommandGuiRvizPanel::OnInitAll(wxCommandEvent &event)
00371 {
00372 cob_script_server::ScriptGoal goal;
00373 bool success = true;
00374
00375 goal.function_name = "init";
00376
00377 ROS_INFO("'init all' clicked");
00378
00379 for(Stringlist::const_iterator ci = init_buttons_.begin(); ci != init_buttons_.end(); ci++)
00380 {
00381 goal.component_name = *ci;
00382
00383 action_client_->sendGoal(goal);
00384 action_client_->waitForResult(ros::Duration(1.0));
00385
00386 if("SUCCEEDED" != action_client_->getState().toString())
00387 {
00388 success = false;
00389 ROS_INFO("warning: component %s not properly initialized\n", goal.component_name.c_str());
00390 }
00391
00392 ROS_INFO("current state: %s\n", action_client_->getState().toString().c_str());
00393 }
00394
00395 if(false != success)
00396 {
00397 statuslabel_->SetLabel(wxT("\n Status: OK"));
00398 this->GetSizer()->Layout();
00399
00400 ROS_INFO("all components initialized\n");
00401 }
00402 else
00403 {
00404
00405 statuslabel_->SetLabel(wxT("\nstatus: \nno connect. to action server!\n\n"));
00406
00407 this->GetSizer()->Layout();
00408
00409 ROS_DEBUG_ONCE("Error! - no connection to action server!\n");
00410 }
00411 }
00412
00413
00414 void CommandGuiRvizPanel::OnRecoverAll(wxCommandEvent &event)
00415 {
00416 cob_script_server::ScriptGoal goal;
00417 bool success = true;
00418
00419 goal.function_name = "recover";
00420
00421 ROS_INFO("'recover all' clicked");
00422
00423 for(Stringlist::const_iterator ci = recover_buttons_.begin(); ci != recover_buttons_.end(); ci++)
00424 {
00425 goal.component_name = *ci;
00426
00427 action_client_->sendGoal(goal);
00428 action_client_->waitForResult(ros::Duration(1.0));
00429
00430 if("SUCCEEDED" != action_client_->getState().toString())
00431 {
00432 success = false;
00433 ROS_INFO("warning: component %s not properly recovered\n", goal.component_name.c_str());
00434 }
00435
00436 ROS_INFO("current state: %s\n", action_client_->getState().toString().c_str());
00437 }
00438
00439 if(false != success)
00440 {
00441 statuslabel_->SetLabel(wxT("\n Status: OK"));
00442 this->GetSizer()->Layout();
00443
00444 ROS_INFO("all components recovered\n");
00445 }
00446 else
00447 {
00448
00449 statuslabel_->SetLabel(wxT("\nstatus: \nno connect. to action server!\n\n"));
00450
00451 this->GetSizer()->Layout();
00452
00453 ROS_DEBUG_ONCE("Error! - no connection to action server!\n");
00454 }
00455 }
00456
00457
00458 inline void CommandGuiRvizPanel::planned_toggle(wxCommandEvent &event)
00459 {
00460 planning_enabled = !planning_enabled;
00461 }
00462
00463
00464 inline void CommandGuiRvizPanel::base_mode_toggle(wxCommandEvent &event)
00465 {
00466 base_diff_enabled = !base_diff_enabled;
00467 }
00468
00469
00470 inline wxString CommandGuiRvizPanel::TowxString(const std::string &temp) const
00471 {
00472 return wxString(temp.c_str(), wxConvUTF8);
00473 }
00474
00475
00476 inline std::string CommandGuiRvizPanel::TostlString(XmlRpc::XmlRpcValue temp) const
00477 {
00478 return static_cast<std::string>(temp);
00479 }
00480
00481
00482 inline std::string CommandGuiRvizPanel::TostlString(wxString temp) const
00483 {
00484 return std::string(temp.mb_str());
00485 }
00486
00487 }