cob_control_mode_adapter_node.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 #include <string>
19 #include <vector>
20 #include <ros/ros.h>
21 #include <std_msgs/Float64.h>
22 #include <std_msgs/Float64MultiArray.h>
23 #include <controller_manager_msgs/LoadController.h>
24 #include <controller_manager_msgs/SwitchController.h>
25 #include <boost/thread/mutex.hpp>
26 
28 {
29 public:
30  bool initialize()
31  {
32  bool success = false;
33 
34  joint_names_.clear();
36  traj_controller_names_.clear();
37  pos_controller_names_.clear();
38  vel_controller_names_.clear();
41 
42  has_traj_controller_ = false;
43  has_pos_controller_ = false;
44  has_vel_controller_ = false;
45 
47 
48  // wait for services from controller manager
49  while (!ros::service::waitForService("controller_manager/load_controller", ros::Duration(5.0))) {;}
50 
51  if (ros::service::exists("controller_manager/load_controller", false))
52  {
53  load_client_ = nh_.serviceClient<controller_manager_msgs::LoadController>("controller_manager/load_controller");
54  }
55  else
56  {
57  ROS_ERROR("...Load service not available!");
58  return false;
59  }
60 
61  while (!ros::service::waitForService("controller_manager/switch_controller", ros::Duration(5.0))) {;}
62 
63  if (ros::service::exists("controller_manager/switch_controller", false))
64  {
65  switch_client_ = nh_.serviceClient<controller_manager_msgs::SwitchController>("controller_manager/switch_controller");
66  }
67  else
68  {
69  ROS_ERROR("...Load service not available!");
70  return false;
71  }
72 
73  std::string param = "max_command_silence";
74  if (nh_.hasParam(param))
75  {
77  }
78  else
79  {
80  ROS_ERROR("Parameter %s not set, using default 0.3s...", param.c_str());
82  }
83 
84  // List of controlled joints
85  param = "joint_names";
86  if (!nh_.getParam(param, joint_names_))
87  {
88  ROS_ERROR("Parameter %s not set, shutting down node...", param.c_str());
89  nh_.shutdown();
90  }
91 
92  std::string joint_trajectory_controller_name = nh_.param<std::string>("joint_trajectory_controller_name", "joint_trajectory_controller");
93 
94  if (nh_.hasParam(joint_trajectory_controller_name))
95  {
96  has_traj_controller_ = true;
97  traj_controller_names_.push_back(joint_trajectory_controller_name);
98  ROS_DEBUG_STREAM(nh_.getNamespace() << " supports '" << joint_trajectory_controller_name << "'");
99  }
100 
101  std::string joint_group_position_controller_name = nh_.param<std::string>("joint_group_position_controller_name", "joint_group_position_controller");
102 
103  if (nh_.hasParam(joint_group_position_controller_name))
104  {
105  has_pos_controller_ = true;
106  pos_controller_names_.push_back(joint_group_position_controller_name);
107  ROS_DEBUG_STREAM(nh_.getNamespace() << " supports '" << joint_group_position_controller_name << "'");
108  }
109 
110 
111  std::string joint_group_velocity_controller_name = nh_.param<std::string>("joint_group_velocity_controller_name", "joint_group_velocity_controller");
112 
113  if (nh_.hasParam(joint_group_velocity_controller_name))
114  {
115  has_vel_controller_ = true;
116  vel_controller_names_.push_back(joint_group_velocity_controller_name);
117  ROS_DEBUG_STREAM(nh_.getNamespace() << " supports '" << joint_group_velocity_controller_name << "'");
118  }
119 
120  // load all required controllers
122  {
123  for (unsigned int i = 0; i < traj_controller_names_.size(); i++)
124  {
126  }
127  }
129  {
130  for (unsigned int i = 0; i < pos_controller_names_.size(); i++)
131  {
133  }
134  cmd_pos_sub_ = nh_.subscribe(joint_group_position_controller_name+"/command", 1, &CobControlModeAdapter::cmd_pos_cb, this);
135  }
137  {
138  for (unsigned int i = 0; i < vel_controller_names_.size(); i++)
139  {
141  }
142  cmd_vel_sub_ = nh_.subscribe(joint_group_velocity_controller_name+"/command", 1, &CobControlModeAdapter::cmd_vel_cb, this);
143  }
144 
145  // start trajectory controller by default
147  {
150  }
151 
152  update_rate_ = 100; // [hz]
154 
155  return true;
156  }
157 
158  bool loadController(std::string load_controller)
159  {
160  controller_manager_msgs::LoadController load_srv;
161  load_srv.request.name = load_controller;
162  if (load_client_.call(load_srv))
163  {
164  if (load_srv.response.ok)
165  {
166  ROS_INFO("%s loaded", load_controller.c_str());
167  return true;
168  }
169  else
170  {
171  ROS_ERROR("Could not load controllers");
172  }
173  }
174  else
175  {
176  ROS_ERROR("ServiceCall failed: load_controller");
177  }
178 
179  return false;
180  }
181 
182 
183  bool switchController(std::vector< std::string > start_controllers, std::vector< std::string > stop_controllers)
184  {
185  controller_manager_msgs::SwitchController switch_srv;
186  switch_srv.request.start_controllers = start_controllers;
187  switch_srv.request.stop_controllers = stop_controllers;
188  switch_srv.request.strictness = 2; // STRICT
189 
190  if (switch_client_.call(switch_srv))
191  {
192  if (switch_srv.response.ok)
193  {
194  std::string str_start;
195  std::string str_stop;
196 
197  if (start_controllers.empty())
198  {
199  str_start = "no_start_controller_defined";
200  }
201  else
202  {
203  str_start = start_controllers.back();
204  }
205  if (stop_controllers.empty())
206  {
207  str_stop = "no_stop_controller_defined";
208  }
209  else
210  {
211  str_stop = stop_controllers.back();
212  }
213 
214  ROS_INFO("Switched Controllers. From %s to %s", str_stop.c_str(), str_start.c_str());
215 
216  current_controller_names_ = start_controllers;
217  return true;
218  }
219  else
220  {
221  ROS_ERROR("Could not switch controllers");
222  }
223  }
224  else
225  {
226  ROS_ERROR("ServiceCall failed: switch_controller");
227  }
228 
229  return false;
230  }
231 
232  void cmd_pos_cb(const std_msgs::Float64MultiArray::ConstPtr& msg)
233  {
234  boost::mutex::scoped_lock lock(mutex_);
236  }
237 
238  void cmd_vel_cb(const std_msgs::Float64MultiArray::ConstPtr& msg)
239  {
240  boost::mutex::scoped_lock lock(mutex_);
242  }
243 
244  void update(const ros::TimerEvent& event)
245  {
246  if (!nh_.ok()) {return;}
247 
248  boost::mutex::scoped_lock lock(mutex_);
249 
250  ros::Duration period_vel = event.current_real - last_vel_command_;
251  ros::Duration period_pos = event.current_real - last_pos_command_;
252 
253  lock.unlock();
254 
255  if (has_vel_controller_ && (period_vel.toSec() < max_command_silence_))
256  {
258  {
260  if (!success)
261  {
262  ROS_ERROR("Unable to switch to velocity_controllers. Not executing command...");
263  }
264  else
265  {
266  ROS_INFO("Successfully switched to velocity_controllers");
268  }
269  }
270  }
271  else if (has_pos_controller_ && (period_pos.toSec() < max_command_silence_))
272  {
274  {
276  if (!success)
277  {
278  ROS_ERROR("Unable to switch to position_controllers. Not executing command...");
279  }
280  else
281  {
282  ROS_INFO("Successfully switched to position_controllers");
284  }
285  }
286  }
287  else if (has_traj_controller_)
288  {
290  {
292  {
293  ROS_INFO("Have not heard a pos command for %f seconds, switched back to trajectory_controller", period_pos.toSec());
294  }
295  else
296  {
297  ROS_INFO("Have not heard a vel command for %f seconds, switched back to trajectory_controller", period_vel.toSec());
298  }
300 
301  if (success)
302  {
304  }
305  else
306  {
307  ROS_ERROR("Unable to switch to trajectory_controller. Not executing command...");
308  }
309  }
310  }
311  else
312  {
313  ROS_ERROR_STREAM(nh_.getNamespace() << " does not support 'joint_trajectory_controller' and no other controller was started yet");
314  }
315  }
316 
317 private:
319 
321  double update_rate_;
322 
323  std::vector< std::string > joint_names_;
324 
325  enum
326  {
329 
330  std::vector< std::string > current_controller_names_;
331  std::vector< std::string > traj_controller_names_;
332  std::vector< std::string > pos_controller_names_;
333  std::vector< std::string > vel_controller_names_;
334 
338 
341 
344 
348  boost::mutex mutex_;
349 };
350 
351 
352 int main(int argc, char** argv)
353 {
354  ros::init(argc, argv, "cob_control_mode_adapter_node");
355  ros::AsyncSpinner spinner(0);
356  spinner.start();
357 
359 
360  if (!ccma->initialize())
361  {
362  ROS_ERROR("Failed to initialize CobControlModeAdapter");
363  return -1;
364  }
365 
367  return 0;
368 }
369 
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
std::vector< std::string > joint_names_
bool param(const std::string &param_name, T &param_val, const T &default_val)
void update(const ros::TimerEvent &event)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
std::vector< std::string > current_controller_names_
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
bool call(MReq &req, MRes &res)
void cmd_pos_cb(const std_msgs::Float64MultiArray::ConstPtr &msg)
std::vector< std::string > traj_controller_names_
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
bool switchController(std::vector< std::string > start_controllers, std::vector< std::string > stop_controllers)
enum CobControlModeAdapter::@0 current_control_mode_
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
const std::string & getNamespace() const
#define ROS_DEBUG_STREAM(args)
int main(int argc, char **argv)
std::vector< std::string > vel_controller_names_
void cmd_vel_cb(const std_msgs::Float64MultiArray::ConstPtr &msg)
bool getParam(const std::string &key, std::string &s) const
static Time now()
ROSCPP_DECL bool exists(const std::string &service_name, bool print_failure_reason)
bool ok() const
bool loadController(std::string load_controller)
bool hasParam(const std::string &key) const
#define ROS_ERROR_STREAM(args)
#define ROS_ERROR(...)
std::vector< std::string > pos_controller_names_
ROSCPP_DECL void waitForShutdown()
ROSCPP_DECL bool waitForService(const std::string &service_name, int32_t timeout)


cob_control_mode_adapter
Author(s): Felix Messmer
autogenerated on Thu Apr 8 2021 02:39:31