virtual_shadowhand.cpp
Go to the documentation of this file.
1 
28 
29 #include <time.h>
30 #include <ros/ros.h>
31 
32 #include <boost/algorithm/string.hpp>
33 
34 #ifdef GAZEBO
35 #include <std_msgs/Float64.h>
36 #endif
37 
38 #include <urdf/model.h>
40 #include <map>
41 #include <string>
42 #include <vector>
43 
44 namespace shadowrobot
45 {
47  SRArticulatedRobot(), n_tilde("~")
48  {
49 #ifdef GAZEBO
50  ROS_INFO("This ROS interface is built for Gazebo.");
51  // initialises the subscriber to the Gazebo joint_states messages
52  std::string prefix;
53  std::string searched_param;
54 
55  n_tilde.searchParam("gazebo_joint_states_prefix", searched_param);
56  n_tilde.param(searched_param, prefix, std::string());
57  std::string full_topic = prefix + "joint_states";
58  gazebo_subscriber = node.subscribe(full_topic, 2, &VirtualShadowhand::gazeboCallback, this);
59 #else
60  ROS_INFO("This ROS interface is not built for Gazebo.");
61 #endif
62 
63  srand(time(NULL));
64  initializeMap();
65  }
66 
68  {
69  }
70 
72  {
73  joints_map_mutex.lock();
74  parameters_map_mutex.lock();
75  controllers_map_mutex.lock();
76 
77 
78  JointData tmpData;
79  JointData tmpDataZero;
80  JointControllerData tmpController;
81  tmpDataZero.isJointZero = 1;
82  tmpDataZero.max = 180.0;
83 
84 #ifdef GAZEBO
85  std::string topic_prefix = "/sh_";
86  std::string topic_suffix = "_mixed_position_velocity_controller/command";
87  std::string full_topic = "";
88 #endif
89 
90  // Get the urdf model from the parameter server
91  std::string robot_desc_string;
92  node.param("hand_description", robot_desc_string, std::string());
93  urdf::Model robot_model;
94  if (!robot_model.initString(robot_desc_string))
95  {
96  ROS_ERROR("Failed to parse urdf file");
97  return;
98  }
99 
100  std::map<std::string, boost::shared_ptr<urdf::Joint> > all_joints = robot_model.joints_;
101  std::map<std::string, boost::shared_ptr<urdf::Joint> >::const_iterator iter = all_joints.begin();
102  ROS_DEBUG("All the Hand joints: ");
103 
104 #ifdef GAZEBO
105  // index of the publisher to the Gazebo controller
106  int tmp_index = 0;
107 #endif
108 
109  for (; iter != all_joints.end(); ++iter)
110  {
111  if (iter->second->type == urdf::Joint::REVOLUTE)
112  {
113  std::string current_joint_name = iter->first;
114 
115  ROS_DEBUG_STREAM(" joint: " << current_joint_name << '\t' << iter->second);
116 
117  // check if we need to create a joint 0
118  // create them when we have the joint 2
119 
120 #ifdef GAZEBO
121  // The joint 1 is not controlled directly in Gazebo (the controller
122  // controls joint 0)
123  bool no_controller = false;
124 #endif
125 
126  bool create_joint_zero = false;
127  boost::algorithm::to_lower(current_joint_name);
128  if (current_joint_name == "ffj2" || current_joint_name == "mfj2"
129  || current_joint_name == "rfj2" || current_joint_name == "lfj2")
130  {
131  create_joint_zero = true;
132 
133 #ifdef GAZEBO
134  no_controller = true;
135 #endif
136  }
137 
138 #ifdef GAZEBO
139  if (current_joint_name == "ffj1" || current_joint_name == "mfj1"
140  || current_joint_name == "rfj1" || current_joint_name == "lfj1")
141  {
142  no_controller = true;
143  }
144 #endif
145 
146  if (create_joint_zero)
147  {
148 #ifdef GAZEBO
149  full_topic = topic_prefix + std::string(1, current_joint_name[0]) + "fj0" + topic_suffix;
150  gazebo_publishers.push_back(node.advertise<std_msgs::Float64>(full_topic, 2));
151  tmpDataZero.publisher_index = tmp_index;
152 
153  ++tmp_index;
154 #endif
155  boost::algorithm::to_upper(current_joint_name);
156  joints_map[std::string(1, current_joint_name[0]) + "FJ0"] = tmpDataZero;
157  controllers_map[std::string(1, current_joint_name[0]) + "FJ0"] = tmpController;
158 
159  tmpData.min = sr_math_utils::to_degrees(iter->second->limits->lower);
160  tmpData.max = sr_math_utils::to_degrees(iter->second->limits->upper);
161  joints_map[current_joint_name] = tmpData;
162  controllers_map[current_joint_name] = tmpController;
163  }
164  else
165  {
166 #ifdef GAZEBO
167  if (!no_controller)
168  {
169  boost::algorithm::to_lower(current_joint_name);
170  full_topic = topic_prefix + current_joint_name + topic_suffix;
171  gazebo_publishers.push_back(node.advertise<std_msgs::Float64>(full_topic, 2));
172  tmpData.publisher_index = tmp_index;
173  ++tmp_index;
174  }
175 #endif
176  tmpData.min = sr_math_utils::to_degrees(iter->second->limits->lower);
177  tmpData.max = sr_math_utils::to_degrees(iter->second->limits->upper);
178  boost::algorithm::to_upper(current_joint_name);
179  joints_map[current_joint_name] = tmpData;
180  controllers_map[current_joint_name] = tmpController;
181  }
182  }
183  }
184 
185  parameters_map["d"] = PARAM_d;
186  parameters_map["i"] = PARAM_i;
187  parameters_map["p"] = PARAM_p;
188  parameters_map["target"] = PARAM_target;
189  parameters_map["sensor"] = PARAM_sensor;
190 
191  parameters_map["valve"] = PARAM_valve;
192  parameters_map["dead"] = PARAM_deadband;
193  parameters_map["deadband"] = PARAM_deadband;
194  parameters_map["imax"] = PARAM_imax;
196  parameters_map["shift"] = PARAM_shift;
198 
199  // ! the parameters for the motors
200  parameters_map["motor_maxforce"] = PARAM_motor_maxforce;
201  parameters_map["motor_safeforce"] = PARAM_motor_safeforce;
202 
203  parameters_map["force_p"] = PARAM_force_p;
204  parameters_map["force_i"] = PARAM_force_i;
205  parameters_map["force_d"] = PARAM_force_d;
206 
207  parameters_map["force_imax"] = PARAM_force_imax;
208  parameters_map["force_out_shift"] = PARAM_force_out_shift;
209  parameters_map["force_deadband"] = PARAM_force_deadband;
210  parameters_map["force_offset"] = PARAM_force_offset;
211 
212  parameters_map["sensor_imax"] = PARAM_sensor_imax;
213  parameters_map["sensor_out_shift"] = PARAM_sensor_out_shift;
214  parameters_map["sensor_deadband"] = PARAM_sensor_deadband;
215  parameters_map["sensor_offset"] = PARAM_sensor_offset;
217  parameters_map["max_temperature"] = PARAM_max_temperature;
218  parameters_map["max_current"] = PARAM_max_current;
219 
220  controllers_map_mutex.unlock();
221  parameters_map_mutex.unlock();
222  joints_map_mutex.unlock();
223  }
224 
225  int16_t VirtualShadowhand::sendupdate(std::string joint_name, double target)
226  {
227  joints_map_mutex.lock();
228 
229  JointsMap::iterator iter = joints_map.find(joint_name);
230 #ifdef GAZEBO
231  std_msgs::Float64 target_msg;
232 #endif
233 
234  // not found
235  if (iter == joints_map.end())
236  {
237  ROS_DEBUG("Joint %s not found", joint_name.c_str());
238 
239  joints_map_mutex.unlock();
240  return -1;
241  }
242  JointData joint_0_data = JointData(iter->second);
243 
244  // in total simulation:
245  // if joint 0, send 1/2 of the target to joint 1 and other half to
246  // 2;
247  // if using gazebo, we just send the target to the joint 0 controller
248  // which is then controlling both joints.
249  if (iter->second.isJointZero == 1)
250  {
251  // push target and position to the given target for Joint 0
252  JointData tmpData0 = JointData(iter->second);
253  if (target < tmpData0.min)
254  {
255  target = tmpData0.min;
256  }
257  if (target > tmpData0.max)
258  {
259  target = tmpData0.max;
260  }
261 
262 #ifndef GAZEBO
263  tmpData0.position = target;
264 #endif
265  tmpData0.target = target;
266 
267  joints_map[joint_name] = tmpData0;
268 
269  ++iter;
270  JointData tmpData1 = JointData(iter->second);
271 #ifdef GAZEBO
272  // gazebo targets are in radians
273  target_msg.data = toRad(target);
274  gazebo_publishers[joint_0_data.publisher_index].publish(target_msg);
275 #else
276  tmpData1.position = target / 2.0;
277 #endif
278  tmpData1.target = target / 2.0;
279 
280  joints_map[iter->first] = tmpData1;
281 
282  ++iter;
283  JointData tmpData2 = JointData(iter->second);
284 #ifdef GAZEBO
285  // we've already send the data to the joint 0 controller
286 #else
287  tmpData2.position = target / 2.0;
288 #endif
289  tmpData2.target = target / 2.0;
290 
291  joints_map[iter->first] = tmpData2;
292 
293  joints_map_mutex.unlock();
294  return 0;
295  }
296 
297  // joint found
298  JointData tmpData(iter->second);
299 
300  if (target < tmpData.min)
301  {
302  target = tmpData.min;
303  }
304  if (target > tmpData.max)
305  {
306  target = tmpData.max;
307  }
308 
309 #ifdef GAZEBO
310  // gazebo targets are in radians
311  target_msg.data = toRad(target);
312  gazebo_publishers[tmpData.publisher_index].publish(target_msg);
313 #else
314  tmpData.position = target;
315 #endif
316  tmpData.target = target;
317 
318  joints_map[joint_name] = tmpData;
319 
320  joints_map_mutex.unlock();
321  return 0;
322  }
323 
325  {
326  joints_map_mutex.lock();
327 
328  JointsMap::iterator iter = joints_map.find(joint_name);
329 
330  // joint found
331  if (iter != joints_map.end())
332  {
333  // return the position
334  iter->second.temperature = 0.0;
335  iter->second.current = 0.0;
336 #ifndef GAZEBO
337  iter->second.force = 0.0;
338 #endif
339 
340  JointData tmp = JointData(iter->second);
341 
342  joints_map_mutex.unlock();
343  return tmp;
344  }
345 
346  ROS_ERROR("Joint %s not found.", joint_name.c_str());
347  JointData noData;
348  joints_map_mutex.unlock();
349  return noData;
350  }
351 
353  {
354  joints_map_mutex.lock();
355 
356  for (JointsMap::const_iterator it = joints_map.begin(); it != joints_map.end(); ++it)
357  {
358  JointData tmpData = it->second;
359  tmpData.temperature = 0.0;
360  tmpData.current = 0.0;
361 #ifndef GAZEBO
362  tmpData.force = 0.0;
363 #endif
364  tmpData.jointIndex = 0;
365  tmpData.flags = "";
366 
367  joints_map[it->first] = tmpData;
368  }
369 
370  JointsMap tmp_map = JointsMap(joints_map);
371  joints_map_mutex.unlock();
372  return tmp_map;
373  }
374 
375  int16_t VirtualShadowhand::setContrl(std::string contrlr_name, JointControllerData ctrlr_data)
376  {
377  controllers_map_mutex.lock();
378 
379  ControllersMap::iterator iter = controllers_map.find(contrlr_name);
380 
381  // joint found
382  if (iter != controllers_map.end())
383  {
384  controllers_map[iter->first] = ctrlr_data;
385  }
386  else
387  {
388  ROS_ERROR("Controller %s not found", contrlr_name.c_str());
389  }
390 
391  controllers_map_mutex.unlock();
392  return 0;
393  }
394 
396  {
397  controllers_map_mutex.lock();
398  ControllersMap::iterator iter = controllers_map.find(contrlr_name);
399 
400  // joint found
401  if (iter != controllers_map.end())
402  {
403  JointControllerData tmp = JointControllerData(iter->second);
404  controllers_map_mutex.unlock();
405  return tmp;
406  }
407 
408  ROS_ERROR("Controller %s not found", contrlr_name.c_str());
409  JointControllerData no_result;
410  controllers_map_mutex.unlock();
411  return no_result;
412  }
413 
414  int16_t VirtualShadowhand::setConfig(std::vector<std::string> myConfig)
415  {
416  ROS_WARN("The set config function is not implemented in the virtual shadowhand.");
417  return 0;
418  }
419 
420  void VirtualShadowhand::getConfig(std::string joint_name)
421  {
422  ROS_WARN("The get config function is not implemented in the virtual shadowhand.");
423  }
424 
425  std::vector<DiagnosticData> VirtualShadowhand::getDiagnostics()
426  {
427  joints_map_mutex.lock();
428  std::vector<DiagnosticData> returnVect;
429 
430  for (JointsMap::const_iterator it = joints_map.begin(); it != joints_map.end(); ++it)
431  {
432  DiagnosticData tmpDiag;
433  tmpDiag.joint_name = it->first;
434  tmpDiag.level = 0;
435  tmpDiag.flags = "";
436  tmpDiag.target_sensor_num = 0;
437  tmpDiag.target = it->second.target;
438  tmpDiag.position_sensor_num = 0;
439  tmpDiag.position = it->second.position;
440 
441  returnVect.push_back(tmpDiag);
442  }
443 
444  joints_map_mutex.unlock();
445  return returnVect;
446  }
447 
448 #ifdef GAZEBO
449  void VirtualShadowhand::gazeboCallback(const sensor_msgs::JointStateConstPtr &msg)
450  {
451  joints_map_mutex.lock();
452 
453  // loop on all the names in the joint_states message
454  for (unsigned int index = 0; index < msg->name.size(); ++index)
455  {
456  std::string joint_name = msg->name[index];
457  JointsMap::iterator iter = joints_map.find(joint_name);
458  // not found => can be a joint from the arm / hand
459  if (iter == joints_map.end())
460  {
461  continue;
462  }
463 
464  // joint found
465  JointData tmpData(iter->second);
466 
467  tmpData.position = toDegrees(msg->position[index]);
468  tmpData.force = msg->effort[index];
469 
470  joints_map[joint_name] = tmpData;
471  }
472 
473  // push the sum of J1+J2 to the J0s
474  for (JointsMap::const_iterator it = joints_map.begin(); it != joints_map.end(); ++it)
475  {
476  JointData tmpData = it->second;
477  if (tmpData.isJointZero == 1)
478  {
479  std::string joint_name = it->first;
480  double position = 0.0;
481 
482  // get the position from joint 1
483  ++it;
484  JointData tmpData1 = JointData(it->second);
485  position += tmpData1.position;
486 
487  // get the position from joint 2
488  ++it;
489  JointData tmpData2 = JointData(it->second);
490  position += tmpData2.position;
491 
492  tmpData.position = position;
493 
494  joints_map[joint_name] = tmpData;
495  }
496  }
497 
498  joints_map_mutex.unlock();
499  }
500 
501 #endif
502 } // namespace shadowrobot
503 
504 
505 /* For the emacs weenies in the crowd.
506 Local Variables:
507  c-basic-offset: 2
508 End:
509 */
msg
virtual int16_t setContrl(std::string contrlr_name, JointControllerData ctrlr_data)
virtual JointControllerData getContrl(std::string ctrlr_name)
ros::NodeHandle node
ROS Node handles.
virtual int16_t setConfig(std::vector< std::string > myConfig)
URDF_EXPORT bool initString(const std::string &xmlstring)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
std::string flags
a string containing flags: FORCE, TEMPERATURE, ... indicating the different cutouts / warning sent by...
std::string joint_name
the name of the joint
std::map< std::string, JointData > JointsMap
int target_sensor_num
the channel number of the target sensor
int position_sensor_num
the channel number of the position sensor
virtual std::vector< DiagnosticData > getDiagnostics()
static double to_degrees(double rad)
#define ROS_WARN(...)
virtual void getConfig(std::string joint_name)
ControllersMap controllers_map
Contains the mapping between the controller names and their data.
#define ROS_INFO(...)
bool searchParam(const std::string &key, std::string &result) const
bool param(const std::string &param_name, T &param_val, const T &default_val) const
JointsMap joints_map
A mapping between the joint names and the information regarding those joints.
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
#define ROS_DEBUG_STREAM(args)
ParametersMap parameters_map
A mapping between the parameter names and their values.
This is a parent class for the different types of Shadowhand we can have. It makes it possible to swa...
virtual int16_t sendupdate(std::string joint_name, double target)
int16_t level
the level of alert: 0 = OK, 1 = WARNING, 2 = ERROR
double target
the actual value of the target
#define ROS_ERROR(...)
virtual JointData getJointData(std::string joint_name)
double position
the actual value of the position
#define ROS_DEBUG(...)
The Virtual Shadowhand can be used as a simulator. As both the real hand and the virtual hand are chi...


sr_hand
Author(s): Ugo Cupcic
autogenerated on Tue Oct 13 2020 03:55:53