sdh_only.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 // ##################
19 // #### includes ####
20 // standard includes
21 #include <unistd.h>
22 #include <map>
23 #include <string>
24 #include <vector>
25 
26 // ROS includes
27 #include <ros/ros.h>
28 #include <urdf/model.h>
30 
31 // ROS message includes
32 #include <std_msgs/Float64MultiArray.h>
33 #include <trajectory_msgs/JointTrajectory.h>
34 #include <sensor_msgs/JointState.h>
35 #include <control_msgs/FollowJointTrajectoryAction.h>
36 #include <control_msgs/JointTrajectoryControllerState.h>
37 #include <schunk_sdh/TemperatureArray.h>
38 
39 // ROS service includes
40 #include <std_srvs/Trigger.h>
41 #include <cob_srvs/SetString.h>
42 
43 // ROS diagnostic msgs
44 #include <diagnostic_msgs/DiagnosticArray.h>
45 
46 // external includes
47 #include <schunk_sdh/sdh.h>
48 
54 class SdhNode
55 {
56 public:
59 
60 private:
61  // declaration of topics to publish
66 
67  // topic subscribers
69 
70  // service servers
79 
80  // actionlib server
82  std::string action_name_;
83 
84  // service clients
85  // --
86 
87  // other variables
88  SDH::cSDH *sdh_;
89  std::vector<SDH::cSDH::eAxisState> state_;
90 
91  std::string sdhdevicetype_;
92  std::string sdhdevicestring_;
93  int sdhdevicenum_;
95  double timeout_;
96 
97  bool isInitialized_;
98  bool isError_;
99  int DOF_;
100  double pi_;
101 
102  trajectory_msgs::JointTrajectory traj_;
103 
104  std::vector<std::string> joint_names_;
105  std::vector<int> axes_;
106  std::vector<double> targetAngles_; // in degrees
107  std::vector<double> velocities_; // in rad/s
108  bool hasNewGoal_;
109  std::string operationMode_;
110 
111  static const std::vector<std::string> temperature_names_;
112 
113 public:
119  SdhNode(std::string name) :
120  as_(nh_, name, boost::bind(&SdhNode::executeCB, this, _1), false), action_name_(name)
121  {
122  nh_ = ros::NodeHandle("~");
123  pi_ = 3.1415926;
124  isError_ = false;
125 
126  as_.start();
127  }
128 
133  {
134  if (isInitialized_)
135  sdh_->Close();
136  delete sdh_;
137  }
138 
142  bool init()
143  {
144  // initialize member variables
145  isInitialized_ = false;
146  hasNewGoal_ = false;
147 
148  // implementation of topics to publish
149  topicPub_JointState_ = nh_.advertise<sensor_msgs::JointState>("joint_states", 1);
150  topicPub_ControllerState_ = nh_.advertise<control_msgs::JointTrajectoryControllerState>(
151  "joint_trajectory_controller/state", 1);
152  topicPub_Diagnostics_ = nh_.advertise<diagnostic_msgs::DiagnosticArray>("/diagnostics", 1);
153  topicPub_Temperature_ = nh_.advertise<schunk_sdh::TemperatureArray>("temperature", 1);
154 
155  // pointer to sdh
156  sdh_ = new SDH::cSDH(false, false, 0); // (_use_radians=false, bool _use_fahrenheit=false, int _debug_level=0)
157 
158  // implementation of service servers
159  srvServer_Init_ = nh_.advertiseService("init", &SdhNode::srvCallback_Init, this);
160  srvServer_Stop_ = nh_.advertiseService("stop", &SdhNode::srvCallback_Stop, this);
161  srvServer_Recover_ = nh_.advertiseService("recover", &SdhNode::srvCallback_Init, this); // HACK: There is no recover implemented yet, so we execute a init
162  srvServer_SetOperationMode_ = nh_.advertiseService("set_operation_mode",
164 
165  srvServer_EmergencyStop_ = nh_.advertiseService("emergency_stop", &SdhNode::srvCallback_EmergencyStop, this);
166  srvServer_Disconnect_ = nh_.advertiseService("shutdown", &SdhNode::srvCallback_Disconnect, this);
167 
168  srvServer_MotorOn_ = nh_.advertiseService("motor_on", &SdhNode::srvCallback_MotorPowerOn, this);
169  srvServer_MotorOff_ = nh_.advertiseService("motor_off", &SdhNode::srvCallback_MotorPowerOff, this);
170 
171  subSetVelocitiesRaw_ = nh_.subscribe("joint_group_velocity_controller/command", 1,
173 
174  // getting hardware parameters from parameter server
175  nh_.param("sdhdevicetype", sdhdevicetype_, std::string("PCAN"));
176  nh_.param("sdhdevicestring", sdhdevicestring_, std::string("/dev/pcan0"));
177  nh_.param("sdhdevicenum", sdhdevicenum_, 0);
178 
179  nh_.param("baudrate", baudrate_, 1000000);
180  nh_.param("timeout", timeout_, static_cast<double>(0.04));
181  nh_.param("id_read", id_read_, 43);
182  nh_.param("id_write", id_write_, 42);
183 
184  // get joint_names from parameter server
185  ROS_INFO("getting joint_names from parameter server");
186  XmlRpc::XmlRpcValue joint_names_param;
187  if (nh_.hasParam("joint_names"))
188  {
189  nh_.getParam("joint_names", joint_names_param);
190  }
191  else
192  {
193  ROS_ERROR("Parameter 'joint_names' not set, shutting down node...");
194  nh_.shutdown();
195  return false;
196  }
197  DOF_ = joint_names_param.size();
198  joint_names_.resize(DOF_);
199  for (int i = 0; i < DOF_; i++)
200  {
201  joint_names_[i] = (std::string)joint_names_param[i];
202  }
203  std::cout << "joint_names = " << joint_names_param << std::endl;
204 
205  // define axes to send to sdh
206  axes_.resize(DOF_);
207  velocities_.resize(DOF_);
208  for (int i = 0; i < DOF_; i++)
209  {
210  axes_[i] = i;
211  }
212  ROS_INFO("DOF = %d", DOF_);
213 
214  state_.resize(axes_.size());
215 
216  nh_.param("OperationMode", operationMode_, std::string("position"));
217  return true;
218  }
224  bool switchOperationMode(const std::string &mode)
225  {
226  hasNewGoal_ = false;
227  sdh_->Stop();
228 
229  try
230  {
231  if (mode == "position")
232  {
233  sdh_->SetController(SDH::cSDH::eCT_POSE);
234  }
235  else if (mode == "velocity")
236  {
237  sdh_->SetController(SDH::cSDH::eCT_VELOCITY);
238  }
239  else
240  {
241  ROS_ERROR_STREAM("Operation mode '" << mode << "' not supported");
242  return false;
243  }
244  sdh_->SetAxisEnable(sdh_->All, 1.0); // TODO: check if necessary
245  }
246  catch (SDH::cSDHLibraryException* e)
247  {
248  ROS_ERROR("An exception was caught: %s", e->what());
249  delete e;
250  return false;
251  }
252 
253  operationMode_ = mode;
254  return true;
255  }
256 
263  void executeCB(const control_msgs::FollowJointTrajectoryGoalConstPtr &goal)
264  {
265  ROS_INFO("sdh: executeCB");
266  if (operationMode_ != "position")
267  {
268  ROS_ERROR("%s: Rejected, sdh not in position mode", action_name_.c_str());
269  as_.setAborted();
270  return;
271  }
272  if (!isInitialized_)
273  {
274  ROS_ERROR("%s: Rejected, sdh not initialized", action_name_.c_str());
275  as_.setAborted();
276  return;
277  }
278 
279  if (goal->trajectory.points.empty() || goal->trajectory.points[0].positions.size() != size_t(DOF_))
280  {
281  ROS_ERROR("%s: Rejected, malformed FollowJointTrajectoryGoal", action_name_.c_str());
282  as_.setAborted();
283  return;
284  }
285  while (hasNewGoal_ == true)
286  usleep(10000);
287 
288  std::map<std::string, int> dict;
289  for (int idx = 0; idx < goal->trajectory.joint_names.size(); idx++)
290  {
291  dict[goal->trajectory.joint_names[idx]] = idx;
292  }
293 
294  targetAngles_.resize(DOF_);
295  targetAngles_[0] = goal->trajectory.points[0].positions[dict["sdh_knuckle_joint"]] * 180.0 / pi_; // sdh_knuckle_joint
296  targetAngles_[1] = goal->trajectory.points[0].positions[dict["sdh_finger_22_joint"]] * 180.0 / pi_; // sdh_finger22_joint
297  targetAngles_[2] = goal->trajectory.points[0].positions[dict["sdh_finger_23_joint"]] * 180.0 / pi_; // sdh_finger23_joint
298  targetAngles_[3] = goal->trajectory.points[0].positions[dict["sdh_thumb_2_joint"]] * 180.0 / pi_; // sdh_thumb2_joint
299  targetAngles_[4] = goal->trajectory.points[0].positions[dict["sdh_thumb_3_joint"]] * 180.0 / pi_; // sdh_thumb3_joint
300  targetAngles_[5] = goal->trajectory.points[0].positions[dict["sdh_finger_12_joint"]] * 180.0 / pi_; // sdh_finger12_joint
301  targetAngles_[6] = goal->trajectory.points[0].positions[dict["sdh_finger_13_joint"]] * 180.0 / pi_; // sdh_finger13_joint
302  ROS_INFO(
303  "received position goal: [['sdh_knuckle_joint', 'sdh_thumb_2_joint', 'sdh_thumb_3_joint', 'sdh_finger_12_joint', 'sdh_finger_13_joint', 'sdh_finger_22_joint', 'sdh_finger_23_joint']] = [%f,%f,%f,%f,%f,%f,%f]",
304  goal->trajectory.points[0].positions[dict["sdh_knuckle_joint"]],
305  goal->trajectory.points[0].positions[dict["sdh_thumb_2_joint"]],
306  goal->trajectory.points[0].positions[dict["sdh_thumb_3_joint"]],
307  goal->trajectory.points[0].positions[dict["sdh_finger_12_joint"]],
308  goal->trajectory.points[0].positions[dict["sdh_finger_13_joint"]],
309  goal->trajectory.points[0].positions[dict["sdh_finger_22_joint"]],
310  goal->trajectory.points[0].positions[dict["sdh_finger_23_joint"]]);
311 
312  hasNewGoal_ = true;
313 
314  usleep(500000); // needed sleep until sdh starts to change status from idle to moving
315 
316  bool finished = false;
317  while (finished == false)
318  {
319  if (as_.isNewGoalAvailable())
320  {
321  ROS_WARN("%s: Aborted", action_name_.c_str());
322  as_.setAborted();
323  return;
324  }
325  for (unsigned int i = 0; i < state_.size(); i++)
326  {
327  ROS_DEBUG("state[%d] = %d", i, state_[i]);
328  if (state_[i] == 0)
329  {
330  finished = true;
331  }
332  else
333  {
334  finished = false;
335  }
336  }
337  usleep(10000);
338  }
339 
340  // set the action state to succeeded
341  ROS_INFO("%s: Succeeded", action_name_.c_str());
342  as_.setSucceeded();
343  }
344 
345  void topicCallback_setVelocitiesRaw(const std_msgs::Float64MultiArrayPtr& velocities)
346  {
347  if (!isInitialized_)
348  {
349  ROS_ERROR("%s: Rejected, sdh not initialized", action_name_.c_str());
350  return;
351  }
352  if (velocities->data.size() != velocities_.size())
353  {
354  ROS_ERROR("Velocity array dimension mismatch");
355  return;
356  }
357  if (operationMode_ != "velocity")
358  {
359  ROS_ERROR("%s: Rejected, sdh not in velocity mode", action_name_.c_str());
360  return;
361  }
362 
363  // TODO: write proper lock!
364  while (hasNewGoal_ == true)
365  usleep(10000);
366 
367  velocities_[0] = velocities->data[0] * 180.0 / pi_; // sdh_knuckle_joint
368  velocities_[1] = velocities->data[5] * 180.0 / pi_; // sdh_finger22_joint
369  velocities_[2] = velocities->data[6] * 180.0 / pi_; // sdh_finger23_joint
370  velocities_[3] = velocities->data[1] * 180.0 / pi_; // sdh_thumb2_joint
371  velocities_[4] = velocities->data[2] * 180.0 / pi_; // sdh_thumb3_joint
372  velocities_[5] = velocities->data[3] * 180.0 / pi_; // sdh_finger12_joint
373  velocities_[6] = velocities->data[4] * 180.0 / pi_; // sdh_finger13_joint
374 
375  hasNewGoal_ = true;
376  }
377 
385  bool srvCallback_Init(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
386  {
387  if (isInitialized_ == false)
388  {
389  // Init Hand connection
390 
391  try
392  {
393  if (sdhdevicetype_.compare("RS232") == 0)
394  {
395  sdh_->OpenRS232(sdhdevicenum_, 115200, 1, sdhdevicestring_.c_str());
396  ROS_INFO("Initialized RS232 for SDH");
397  isInitialized_ = true;
398  }
399  if (sdhdevicetype_.compare("PCAN") == 0)
400  {
401  ROS_INFO("Starting initializing PEAKCAN");
402  sdh_->OpenCAN_PEAK(baudrate_, timeout_, id_read_, id_write_, sdhdevicestring_.c_str());
403  ROS_INFO("Initialized PEAK CAN for SDH");
404  isInitialized_ = true;
405  }
406  if (sdhdevicetype_.compare("ESD") == 0)
407  {
408  ROS_INFO("Starting initializing ESD");
409  if (strcmp(sdhdevicestring_.c_str(), "/dev/can0") == 0)
410  {
411  ROS_INFO("Initializing ESD on device %s", sdhdevicestring_.c_str());
412  sdh_->OpenCAN_ESD(0, baudrate_, timeout_, id_read_, id_write_);
413  }
414  else if (strcmp(sdhdevicestring_.c_str(), "/dev/can1") == 0)
415  {
416  ROS_INFO("Initializin ESD on device %s", sdhdevicestring_.c_str());
417  sdh_->OpenCAN_ESD(1, baudrate_, timeout_, id_read_, id_write_);
418  }
419  else
420  {
421  ROS_ERROR("Currently only support for /dev/can0 and /dev/can1");
422  res.success = false;
423  res.message = "Currently only support for /dev/can0 and /dev/can1";
424  return true;
425  }
426  ROS_INFO("Initialized ESDCAN for SDH");
427  isInitialized_ = true;
428  }
429  }
430  catch (SDH::cSDHLibraryException* e)
431  {
432  ROS_ERROR("An exception was caught: %s", e->what());
433  res.success = false;
434  res.message = e->what();
435  delete e;
436  return true;
437  }
438  if (!switchOperationMode(operationMode_))
439  {
440  res.success = false;
441  res.message = "Could not set operation mode to '" + operationMode_ + "'";
442  return true;
443  }
444  }
445  else
446  {
447  ROS_WARN("...sdh already initialized...");
448  res.success = true;
449  res.message = "sdh already initialized";
450  }
451 
452  res.success = true;
453  return true;
454  }
455 
463  bool srvCallback_Stop(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
464  {
465  ROS_INFO("Stopping sdh");
466 
467  // stopping all arm movements
468  try
469  {
470  sdh_->Stop();
471  }
472  catch (SDH::cSDHLibraryException* e)
473  {
474  ROS_ERROR("An exception was caught: %s", e->what());
475  delete e;
476  }
477 
478  ROS_INFO("Stopping sdh succesfull");
479  res.success = true;
480  return true;
481  }
482 
490  bool srvCallback_Recover(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
491  {
492  ROS_WARN("Service recover not implemented yet");
493  res.success = true;
494  res.message = "Service recover not implemented yet";
495  return true;
496  }
497 
505  bool srvCallback_SetOperationMode(cob_srvs::SetString::Request &req, cob_srvs::SetString::Response &res)
506  {
507  hasNewGoal_ = false;
508  sdh_->Stop();
509  res.success = switchOperationMode(req.data);
510  if (operationMode_ == "position")
511  {
512  sdh_->SetController(SDH::cSDH::eCT_POSE);
513  }
514  else if (operationMode_ == "velocity")
515  {
516  try
517  {
518  sdh_->SetController(SDH::cSDH::eCT_VELOCITY);
519  sdh_->SetAxisEnable(sdh_->All, 1.0);
520  }
521  catch (SDH::cSDHLibraryException* e)
522  {
523  ROS_ERROR("An exception was caught: %s", e->what());
524  delete e;
525  }
526  }
527  else
528  {
529  ROS_ERROR_STREAM("Operation mode '" << req.data << "' not supported");
530  }
531  return true;
532  }
533 
541  bool srvCallback_EmergencyStop(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res) {
542  try {
543  isInitialized_ = false;
544  sdh_->EmergencyStop();
545  sdh_->SetAxisEnable(sdh_->All, 0.0);
546  sdh_->SetAxisMotorCurrent(sdh_->All, 0.0);
547  }
548  catch(const SDH::cSDHLibraryException* e) {
549  ROS_ERROR("An exception was caught: %s", e->what());
550  res.success = false;
551  res.message = e->what();
552  return true;
553  }
554 
555  res.success = true;
556  res.message = "EMERGENCY stop";
557  return true;
558  }
559 
567  bool srvCallback_Disconnect(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res) {
568  try {
569  isInitialized_ = false;
570 
571  sdh_->SetAxisEnable(sdh_->All, 0.0);
572  sdh_->SetAxisMotorCurrent(sdh_->All, 0.0);
573 
574  sdh_->Close();
575  }
576  catch(const SDH::cSDHLibraryException* e) {
577  ROS_ERROR("An exception was caught: %s", e->what());
578  res.success = false;
579  res.message = e->what();
580  return true;
581  }
582 
583  ROS_INFO("Disconnected");
584  res.success = true;
585  res.message = "disconnected from SDH";
586  return true;
587  }
588 
594  bool srvCallback_MotorPowerOn(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res) {
595  try {
596  sdh_->SetAxisEnable(sdh_->All, 1.0);
597  sdh_->SetAxisMotorCurrent(sdh_->All, 0.5);
598  }
599  catch (const SDH::cSDHLibraryException* e) {
600  ROS_ERROR("An exception was caught: %s", e->what());
601  res.success = false;
602  res.message = e->what();
603  return true;
604  }
605  ROS_INFO("Motor power ON");
606  res.success = true;
607  res.message = "Motor ON";
608  return true;
609  }
610 
616  bool srvCallback_MotorPowerOff(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res) {
617  try {
618  sdh_->SetAxisEnable(sdh_->All, 0.0);
619  sdh_->SetAxisMotorCurrent(sdh_->All, 0.0);
620  }
621  catch (const SDH::cSDHLibraryException* e) {
622  ROS_ERROR("An exception was caught: %s", e->what());
623  res.success = false;
624  res.message = e->what();
625  return true;
626  }
627  ROS_INFO("Motor power OFF");
628  res.success = true;
629  res.message = "Motor OFF";
630  return true;
631  }
632 
638  void updateSdh()
639  {
640  ROS_DEBUG("updateJointState");
641  if (isInitialized_ == true)
642  {
643  if (hasNewGoal_ == true)
644  {
645  // stop sdh first when new goal arrived
646  try
647  {
648  sdh_->Stop();
649  }
650  catch (SDH::cSDHLibraryException* e)
651  {
652  ROS_ERROR("An exception was caught: %s", e->what());
653  delete e;
654  }
655 
656  if (operationMode_ == "position")
657  {
658  ROS_DEBUG("moving sdh in position mode");
659 
660  try
661  {
662  sdh_->SetAxisTargetAngle(axes_, targetAngles_);
663  sdh_->MoveHand(false);
664  }
665  catch (SDH::cSDHLibraryException* e)
666  {
667  ROS_ERROR("An exception was caught: %s", e->what());
668  delete e;
669  }
670  }
671  else if (operationMode_ == "velocity")
672  {
673  ROS_DEBUG("moving sdh in velocity mode");
674  try
675  {
676  sdh_->SetAxisTargetVelocity(axes_, velocities_);
677  // ROS_DEBUG_STREAM("velocities: " << velocities_[0] << " "<< velocities_[1] << " "<< velocities_[2] << " "<< velocities_[3] << " "<< velocities_[4] << " "<< velocities_[5] << " "<< velocities_[6]);
678  }
679  catch (SDH::cSDHLibraryException* e)
680  {
681  ROS_ERROR("An exception was caught: %s", e->what());
682  delete e;
683  }
684  }
685  else if (operationMode_ == "effort")
686  {
687  ROS_DEBUG("moving sdh in effort mode");
688  // sdh_->MoveVel(goal->trajectory.points[0].velocities);
689  ROS_WARN("Moving in effort mode currently disabled");
690  }
691  else
692  {
693  ROS_ERROR("sdh neither in position nor in velocity nor in effort mode. OperationMode = [%s]",
694  operationMode_.c_str());
695  }
696 
697  hasNewGoal_ = false;
698  }
699 
700  // read and publish joint angles and velocities
701  std::vector<double> actualAngles;
702  try
703  {
704  actualAngles = sdh_->GetAxisActualAngle(axes_);
705  }
706  catch (SDH::cSDHLibraryException* e)
707  {
708  ROS_ERROR("An exception was caught: %s", e->what());
709  delete e;
710  }
711  std::vector<double> actualVelocities;
712  try
713  {
714  actualVelocities = sdh_->GetAxisActualVelocity(axes_);
715  }
716  catch (SDH::cSDHLibraryException* e)
717  {
718  ROS_ERROR("An exception was caught: %s", e->what());
719  delete e;
720  }
721 
722  ROS_DEBUG("received %d angles from sdh", static_cast<int>(actualAngles.size()));
723 
724  ros::Time time = ros::Time::now();
725 
726  // create joint_state message
727  sensor_msgs::JointState msg;
728  msg.header.stamp = time;
729  msg.name.resize(DOF_);
730  msg.position.resize(DOF_);
731  msg.velocity.resize(DOF_);
732  msg.effort.resize(DOF_);
733  // set joint names and map them to angles
734  msg.name = joint_names_;
735  // ['sdh_knuckle_joint', 'sdh_thumb_2_joint', 'sdh_thumb_3_joint', 'sdh_finger_12_joint', 'sdh_finger_13_joint', 'sdh_finger_22_joint', 'sdh_finger_23_joint']
736  // pos
737  msg.position[0] = actualAngles[0] * pi_ / 180.0; // sdh_knuckle_joint
738  msg.position[1] = actualAngles[3] * pi_ / 180.0; // sdh_thumb_2_joint
739  msg.position[2] = actualAngles[4] * pi_ / 180.0; // sdh_thumb_3_joint
740  msg.position[3] = actualAngles[5] * pi_ / 180.0; // sdh_finger_12_joint
741  msg.position[4] = actualAngles[6] * pi_ / 180.0; // sdh_finger_13_joint
742  msg.position[5] = actualAngles[1] * pi_ / 180.0; // sdh_finger_22_joint
743  msg.position[6] = actualAngles[2] * pi_ / 180.0; // sdh_finger_23_joint
744  // vel
745  msg.velocity[0] = actualVelocities[0] * pi_ / 180.0; // sdh_knuckle_joint
746  msg.velocity[1] = actualVelocities[3] * pi_ / 180.0; // sdh_thumb_2_joint
747  msg.velocity[2] = actualVelocities[4] * pi_ / 180.0; // sdh_thumb_3_joint
748  msg.velocity[3] = actualVelocities[5] * pi_ / 180.0; // sdh_finger_12_joint
749  msg.velocity[4] = actualVelocities[6] * pi_ / 180.0; // sdh_finger_13_joint
750  msg.velocity[5] = actualVelocities[1] * pi_ / 180.0; // sdh_finger_22_joint
751  msg.velocity[6] = actualVelocities[2] * pi_ / 180.0; // sdh_finger_23_joint
752  // publish message
753  topicPub_JointState_.publish(msg);
754 
755  // because the robot_state_publisher doesn't know about the mimic joint, we have to publish the coupled joint separately
756  sensor_msgs::JointState mimicjointmsg;
757  mimicjointmsg.header.stamp = time;
758  mimicjointmsg.name.resize(1);
759  mimicjointmsg.position.resize(1);
760  mimicjointmsg.velocity.resize(1);
761  mimicjointmsg.name[0] = "sdh_finger_21_joint";
762  mimicjointmsg.position[0] = msg.position[0]; // sdh_knuckle_joint = sdh_finger_21_joint
763  mimicjointmsg.velocity[0] = msg.velocity[0]; // sdh_knuckle_joint = sdh_finger_21_joint
764  topicPub_JointState_.publish(mimicjointmsg);
765 
766  // publish controller state message
767  control_msgs::JointTrajectoryControllerState controllermsg;
768  controllermsg.header.stamp = time;
769  controllermsg.joint_names.resize(DOF_);
770  controllermsg.desired.positions.resize(DOF_);
771  controllermsg.desired.velocities.resize(DOF_);
772  controllermsg.actual.positions.resize(DOF_);
773  controllermsg.actual.velocities.resize(DOF_);
774  controllermsg.error.positions.resize(DOF_);
775  controllermsg.error.velocities.resize(DOF_);
776  // set joint names and map them to angles
777  controllermsg.joint_names = joint_names_;
778  // ['sdh_knuckle_joint', 'sdh_thumb_2_joint', 'sdh_thumb_3_joint', 'sdh_finger_12_joint', 'sdh_finger_13_joint', 'sdh_finger_22_joint', 'sdh_finger_23_joint']
779  // desired pos
780  if (targetAngles_.size() != 0)
781  {
782  controllermsg.desired.positions[0] = targetAngles_[0] * pi_ / 180.0; // sdh_knuckle_joint
783  controllermsg.desired.positions[1] = targetAngles_[3] * pi_ / 180.0; // sdh_thumb_2_joint
784  controllermsg.desired.positions[2] = targetAngles_[4] * pi_ / 180.0; // sdh_thumb_3_joint
785  controllermsg.desired.positions[3] = targetAngles_[5] * pi_ / 180.0; // sdh_finger_12_joint
786  controllermsg.desired.positions[4] = targetAngles_[6] * pi_ / 180.0; // sdh_finger_13_joint
787  controllermsg.desired.positions[5] = targetAngles_[1] * pi_ / 180.0; // sdh_finger_22_joint
788  controllermsg.desired.positions[6] = targetAngles_[2] * pi_ / 180.0; // sdh_finger_23_joint
789  }
790  // desired vel
791  // they are all zero
792  // actual pos
793  controllermsg.actual.positions = msg.position;
794  // actual vel
795  controllermsg.actual.velocities = msg.velocity;
796  // error, calculated out of desired and actual values
797  for (int i = 0; i < DOF_; i++)
798  {
799  controllermsg.error.positions[i] = controllermsg.desired.positions[i] - controllermsg.actual.positions[i];
800  controllermsg.error.velocities[i] = controllermsg.desired.velocities[i] - controllermsg.actual.velocities[i];
801  }
802  // publish controller message
803  topicPub_ControllerState_.publish(controllermsg);
804 
805  // read sdh status
806  state_ = sdh_->GetAxisActualState(axes_);
807 
808  // publish temperature
809  schunk_sdh::TemperatureArray temp_array;
810  temp_array.header.stamp = time;
811  const std::vector<double> temp_value = sdh_->GetTemperature(sdh_->all_temperature_sensors);
812  if(temp_value.size()==temperature_names_.size()) {
813  temp_array.name = temperature_names_;
814  temp_array.temperature = temp_value;
815  }
816  else {
817  ROS_ERROR("amount of temperatures mismatch with stored names");
818  }
819  topicPub_Temperature_.publish(temp_array);
820  }
821  else
822  {
823  ROS_DEBUG("sdh not initialized");
824  }
825  // publishing diagnotic messages
826  diagnostic_msgs::DiagnosticArray diagnostics;
827  diagnostics.status.resize(1);
828  // set data to diagnostics
829  if (isError_)
830  {
831  diagnostics.status[0].level = 2;
832  diagnostics.status[0].name = "schunk_powercube_chain";
833  diagnostics.status[0].message = "one or more drives are in Error mode";
834  }
835  else
836  {
837  if (isInitialized_)
838  {
839  diagnostics.status[0].level = 0;
840  diagnostics.status[0].name = nh_.getNamespace(); // "schunk_powercube_chain";
841  diagnostics.status[0].message = "sdh initialized and running";
842  }
843  else
844  {
845  diagnostics.status[0].level = 1;
846  diagnostics.status[0].name = nh_.getNamespace(); // "schunk_powercube_chain";
847  diagnostics.status[0].message = "sdh not initialized";
848  }
849  }
850  // publish diagnostic message
851  topicPub_Diagnostics_.publish(diagnostics);
852  }
853 };
854 
855 const std::vector<std::string> SdhNode::temperature_names_ = {
856  "root",
857  "proximal_finger_1", "distal_finger_1",
858  "proximal_finger_2", "distal_finger_2",
859  "proximal_finger_3", "distal_finger_3",
860  "controller", "pcb"
861 };
862 // SdhNode
863 
869 int main(int argc, char** argv)
870 {
871  // initialize ROS, spezify name of node
872  ros::init(argc, argv, "schunk_sdh");
873 
874  SdhNode sdh_node(ros::this_node::getName() + "/follow_joint_trajectory");
875  if (!sdh_node.init())
876  return 0;
877 
878  ROS_INFO("...sdh node running...");
879 
880  double frequency;
881  if (sdh_node.nh_.hasParam("frequency"))
882  {
883  sdh_node.nh_.getParam("frequency", frequency);
884  }
885  else
886  {
887  frequency = 5; // Hz
888  ROS_WARN("Parameter frequency not available, setting to default value: %f Hz", frequency);
889  }
890 
891  // sleep(1);
892  ros::Rate loop_rate(frequency); // Hz
893  while (sdh_node.nh_.ok())
894  {
895  // publish JointState
896  sdh_node.updateSdh();
897 
898  // sleep and waiting for messages, callbacks
899  ros::spinOnce();
900  loop_rate.sleep();
901  }
902 
903  return 0;
904 }
905 
std::string sdhdevicetype_
Definition: sdh.cpp:97
bool srvCallback_Recover(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
Executes the service callback for recover.
Definition: sdh_only.cpp:490
std::vector< int > axes_
Definition: sdh.cpp:118
int main(int argc, char **argv)
Main loop of ROS node.
Definition: sdh_only.cpp:869
double pi_
Definition: sdh.cpp:113
ros::ServiceServer srvServer_Init_
Definition: sdh.cpp:76
ros::Publisher topicPub_Temperature_
Definition: sdh.cpp:69
trajectory_msgs::JointTrajectory traj_
Definition: sdh.cpp:115
std::vector< SDH::cSDH::eAxisState > state_
Definition: sdh.cpp:95
void publish(const boost::shared_ptr< M > &message) const
bool srvCallback_EmergencyStop(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
Executes the service callback for emergency_stop.
Definition: sdh.cpp:592
ros::ServiceServer srvServer_MotorOff_
Definition: sdh.cpp:83
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
int size() const
SDH::cSDH * sdh_
Definition: sdh.cpp:93
bool isInitialized_
Definition: sdh.cpp:109
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
int id_read_
Definition: sdh.cpp:106
bool srvCallback_Disconnect(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
Executes the service callback for disconnect.
Definition: sdh.cpp:618
bool switchOperationMode(const std::string &mode)
Switches operation mode if possible.
Definition: sdh_only.cpp:224
ros::ServiceServer srvServer_EmergencyStop_
Definition: sdh.cpp:80
ROSCPP_DECL const std::string & getName()
std::string sdhdevicestring_
Definition: sdh.cpp:98
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
ros::Publisher topicPub_JointState_
Definition: sdh.cpp:65
int baudrate_
Definition: sdh.cpp:106
#define ROS_WARN(...)
void setSucceeded(const Result &result=Result(), const std::string &text=std::string(""))
ros::ServiceServer srvServer_SetOperationMode_
Definition: sdh.cpp:79
int id_write_
Definition: sdh.cpp:106
ros::ServiceServer srvServer_Disconnect_
Definition: sdh.cpp:81
SdhNode(std::string name)
Constructor for SdhNode class.
Definition: sdh_only.cpp:119
ros::ServiceServer srvServer_MotorOn_
Definition: sdh.cpp:82
bool srvCallback_MotorPowerOn(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
Enable motor power.
Definition: sdh.cpp:647
int DOF_
Definition: sdh.cpp:112
std::string operationMode_
Definition: sdh.cpp:122
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
ros::ServiceServer srvServer_Recover_
Definition: sdh.cpp:78
const std::string & getNamespace() const
int sdhdevicenum_
Definition: sdh.cpp:99
void executeCB(const control_msgs::FollowJointTrajectoryGoalConstPtr &goal)
Executes the callback from the actionlib.
Definition: sdh.cpp:288
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
~SdhNode()
Destructor for SdhNode class.
Definition: sdh_only.cpp:132
actionlib::SimpleActionServer< control_msgs::FollowJointTrajectoryAction > as_
Definition: sdh.cpp:86
bool srvCallback_MotorPowerOff(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
Disable motor power.
Definition: sdh.cpp:669
bool sleep()
void topicCallback_setVelocitiesRaw(const std_msgs::Float64MultiArrayPtr &velocities)
Definition: sdh.cpp:375
bool isError_
Definition: sdh.cpp:111
void setAborted(const Result &result=Result(), const std::string &text=std::string(""))
bool init()
Initializes node to get parameters, subscribe and publish to topics.
Definition: sdh_only.cpp:142
std::vector< double > targetAngles_
Definition: sdh.cpp:119
std::vector< std::string > joint_names_
Definition: sdh.cpp:117
Implementation of ROS node for sdh.
Definition: sdh.cpp:58
bool getParam(const std::string &key, std::string &s) const
void updateSdh()
Main routine to update sdh.
Definition: sdh_only.cpp:638
ros::Subscriber subSetVelocitiesRaw_
Definition: sdh.cpp:73
ros::NodeHandle nh_
create a handle for this node, initialize node
Definition: sdh.cpp:62
bool srvCallback_Init(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
Executes the service callback for init.
Definition: sdh.cpp:415
std::vector< double > velocities_
Definition: sdh.cpp:120
static Time now()
ros::Publisher topicPub_ControllerState_
Definition: sdh.cpp:66
bool ok() const
bool hasParam(const std::string &key) const
#define ROS_ERROR_STREAM(args)
static const std::vector< std::string > temperature_names_
Definition: sdh.cpp:124
ROSCPP_DECL void spinOnce()
bool srvCallback_Stop(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
Executes the service callback for stop.
Definition: sdh.cpp:525
#define ROS_ERROR(...)
std::string action_name_
Definition: sdh.cpp:87
double timeout_
Definition: sdh.cpp:107
bool hasNewGoal_
Definition: sdh.cpp:121
bool srvCallback_SetOperationMode(cob_srvs::SetString::Request &req, cob_srvs::SetString::Response &res)
Executes the service callback for set_operation_mode.
Definition: sdh.cpp:553
ros::Publisher topicPub_Diagnostics_
Definition: sdh.cpp:68
#define ROS_DEBUG(...)
ros::ServiceServer srvServer_Stop_
Definition: sdh.cpp:77


schunk_sdh
Author(s): Mathias Luedtke , Florian Weisshardt
autogenerated on Mon Nov 25 2019 03:48:23