joint_trajectory_interface.cpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2013, Southwest Research Institute
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  * * Neither the name of the Southwest Research Institute, nor the names
16  * of its contributors may be used to endorse or promote products derived
17  * from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <algorithm>
37 #include <vector>
38 #include <map>
39 #include <string>
40 
46 typedef trajectory_msgs::JointTrajectoryPoint ros_JointTrajPt;
47 typedef motoman_msgs::DynamicJointsGroup ros_dynamicPoint;
48 
50 {
51 namespace joint_trajectory_interface
52 {
53 
54 #define ROS_ERROR_RETURN(rtn, ...) do {ROS_ERROR(__VA_ARGS__); return(rtn);} while (0) // NOLINT(whitespace/braces)
55 
56 bool JointTrajectoryInterface::init(std::string default_ip, int default_port, bool version_0)
57 {
58  std::string ip;
59  int port;
60 
61  // override IP/port with ROS params, if available
62  ros::param::param<std::string>("robot_ip_address", ip, default_ip);
63  ros::param::param<int>("~port", port, default_port);
64 
65  // check for valid parameter values
66  if (ip.empty())
67  {
68  ROS_ERROR("No valid robot IP address found. Please set ROS 'robot_ip_address' param");
69  return false;
70  }
71  if (port <= 0)
72  {
73  ROS_ERROR("No valid robot TCP port found. Please set ROS '~port' param");
74  return false;
75  }
76 
77  char* ip_addr = strdup(ip.c_str()); // connection.init() requires "char*", not "const char*"
78  ROS_INFO("Joint Trajectory Interface connecting to IP address: '%s:%d'", ip_addr, port);
79  default_tcp_connection_.init(ip_addr, port);
80  free(ip_addr);
81 
83 }
84 
85 bool JointTrajectoryInterface::init(SmplMsgConnection* connection)
86 {
87  std::map<int, RobotGroup> robot_groups;
88  if (getJointGroups("topic_list", robot_groups))
89  {
90  this->version_0_ = false;
91  return init(connection, robot_groups);
92  }
93  else
94  {
95  this->version_0_ = true;
96  std::vector<std::string> joint_names;
97  if (!getJointNames("controller_joint_names", "robot_description", joint_names))
98  {
99  ROS_WARN("Unable to read 'controller_joint_names' param. Using standard 6-DOF joint names.");
100  }
101  return init(connection, joint_names);
102  }
103  return false;
104 }
105 
106 bool JointTrajectoryInterface::init(SmplMsgConnection* connection, const std::vector<std::string> &joint_names,
107  const std::map<std::string, double> &velocity_limits)
108 {
109  this->connection_ = connection;
110  this->all_joint_names_ = joint_names;
111  this->joint_vel_limits_ = velocity_limits;
113 
114  // try to read velocity limits from URDF, if none specified
115  if (joint_vel_limits_.empty()
117  ROS_WARN("Unable to read velocity limits from 'robot_description' param. Velocity validation disabled.");
118 
119 
121  "stop_motion", &JointTrajectoryInterface::stopMotionCB, this);
123  "joint_path_command", &JointTrajectoryInterface::jointTrajectoryCB, this);
124  this->sub_joint_trajectory_ = this->node_.subscribe(
125  "joint_path_command", 0, &JointTrajectoryInterface::jointTrajectoryCB, this);
126  this->sub_cur_pos_ = this->node_.subscribe(
127  "joint_states", 1, &JointTrajectoryInterface::jointStateCB, this);
128 
129  return true;
130 }
131 
133  SmplMsgConnection* connection, const std::map<int, RobotGroup> &robot_groups,
134  const std::map<std::string, double> &velocity_limits)
135 {
136  this->connection_ = connection;
137  this->robot_groups_ = robot_groups;
138  this->joint_vel_limits_ = velocity_limits;
140 
141  // try to read velocity limits from URDF, if none specified
142  if (joint_vel_limits_.empty()
144  "robot_description", joint_vel_limits_))
145  ROS_WARN("Unable to read velocity limits from 'robot_description' param. Velocity validation disabled.");
146 
147  // General server and subscriber for compounded trajectories
149  "joint_path_command", &JointTrajectoryInterface::jointTrajectoryExCB, this);
150  this->sub_joint_trajectory_ = this->node_.subscribe(
151  "joint_path_command", 0, &JointTrajectoryInterface::jointTrajectoryExCB, this);
153  "stop_motion", &JointTrajectoryInterface::stopMotionCB, this);
154 
155  for (it_type iterator = this->robot_groups_.begin(); iterator != this->robot_groups_.end(); iterator++)
156  {
157  std::string name_str, ns_str;
158  int robot_id = iterator->first;
159  name_str = iterator->second.get_name();
160  ns_str = iterator->second.get_ns();
161 
162  ros::ServiceServer srv_joint_trajectory;
163  ros::ServiceServer srv_stop_motion;
164  ros::Subscriber sub_joint_trajectory;
165 
166  srv_stop_motion = this->node_.advertiseService(
167  ns_str + "/" + name_str + "/stop_motion",
169  srv_joint_trajectory = this->node_.advertiseService(
170  ns_str + "/" + name_str + "/joint_path_command",
171  &JointTrajectoryInterface::jointTrajectoryExCB, this);
172  sub_joint_trajectory = this->node_.subscribe(
173  ns_str + "/" + name_str + "/joint_path_command", 0,
174  &JointTrajectoryInterface::jointTrajectoryExCB, this);
175 
176  this->srv_stops_[robot_id] = srv_stop_motion;
177  this->srv_joints_[robot_id] = srv_joint_trajectory;
178  this->sub_joint_trajectories_[robot_id] = sub_joint_trajectory;
179 
180  this->sub_cur_pos_ = this->node_.subscribe<sensor_msgs::JointState>(
181  ns_str + "/" + name_str + "/joint_states", 1,
182  boost::bind(&JointTrajectoryInterface::jointStateCB, this, _1, robot_id));
183 
184  this->sub_cur_positions_[robot_id] = this->sub_cur_pos_;
185  }
186 
187 
188  return true;
189 }
190 
192 {
193  trajectoryStop();
195 }
196 
197 bool JointTrajectoryInterface::jointTrajectoryExCB(
198  motoman_msgs::CmdJointTrajectoryEx::Request &req,
199  motoman_msgs::CmdJointTrajectoryEx::Response &res)
200 {
201  motoman_msgs::DynamicJointTrajectoryPtr traj_ptr(
202  new motoman_msgs::DynamicJointTrajectory);
203  *traj_ptr = req.trajectory; // copy message data
204  this->jointTrajectoryExCB(traj_ptr);
205 
206  // no success/fail result from jointTrajectoryCB. Assume success.
207  res.code.val = industrial_msgs::ServiceReturnCode::SUCCESS;
208 
209  return true; // always return true. To distinguish between call-failed and service-unavailable.
210 }
211 
212 
214  industrial_msgs::CmdJointTrajectory::Request &req,
215  industrial_msgs::CmdJointTrajectory::Response &res)
216 {
217  trajectory_msgs::JointTrajectoryPtr traj_ptr(
218  new trajectory_msgs::JointTrajectory);
219  *traj_ptr = req.trajectory; // copy message data
220  this->jointTrajectoryCB(traj_ptr);
221 
222  res.code.val = industrial_msgs::ServiceReturnCode::SUCCESS;
223 
224  return true; // always return true. To distinguish between call-failed and service-unavailable.
225 }
226 
227 void JointTrajectoryInterface::jointTrajectoryExCB(
228  const motoman_msgs::DynamicJointTrajectoryConstPtr &msg)
229 {
230  ROS_INFO("Receiving joint trajectory message Dynamic");
231 
232  // check for STOP command
233  if (msg->points.empty())
234  {
235  ROS_INFO("Empty trajectory received, canceling current trajectory");
236  trajectoryStop();
237  return;
238  }
239 
240  // convert trajectory into robot-format
241  std::vector<SimpleMessage> robot_msgs;
242  if (!trajectory_to_msgs(msg, &robot_msgs))
243  return;
244 
245  // send command messages to robot
246  send_to_robot(robot_msgs);
247 }
248 
249 
251  const trajectory_msgs::JointTrajectoryConstPtr &msg)
252 {
253  ROS_INFO("Receiving joint trajectory message");
254 
255  // check for STOP command
256  if (msg->points.empty())
257  {
258  ROS_INFO("Empty trajectory received, canceling current trajectory");
259  trajectoryStop();
260  return;
261  }
262 
263  // convert trajectory into robot-format
264  std::vector<SimpleMessage> robot_msgs;
265  if (!trajectory_to_msgs(msg, &robot_msgs))
266  return;
267 
268  // send command messages to robot
269  send_to_robot(robot_msgs);
270 }
271 
273  const motoman_msgs::DynamicJointTrajectoryConstPtr& traj,
274  std::vector<SimpleMessage>* msgs)
275 {
276  msgs->clear();
277 
278  std::vector<double>::iterator it;
279 
280  if (traj->points[0].num_groups == 1)
281  {
282  // check for valid trajectory
283  if (!is_valid(*traj))
284  {
285  return false;
286  }
287 
288  for (size_t i = 0; i < traj->points.size(); ++i)
289  {
290  SimpleMessage msg;
291  ros_dynamicPoint rbt_pt, xform_pt;
292 
293 
294  if (!select(traj->joint_names, traj->points[i].groups[0],
295  robot_groups_[traj->points[i].groups[0].group_number].get_joint_names(),
296  &rbt_pt))
297  return false;
298 
299  // transform point data (e.g. for joint-coupling)
300  if (!transform(rbt_pt, &xform_pt))
301  return false;
302 
303  // convert trajectory point to ROS message
304  if (!create_message(i, xform_pt, &msg))
305  return false;
306 
307  msgs->push_back(msg);
308  }
309  }
310  // TODO(thiagodefreitas) : get MAX_NUM_GROUPS for the FS100 controller
311  else if (traj->points[0].num_groups <= 4)
312  {
313  for (size_t i = 0; i < traj->points.size(); ++i)
314  {
315  SimpleMessage msg;
316  create_message_ex(i, traj->points[i], &msg);
317  msgs->push_back(msg);
318  }
319  }
320  return true;
321 }
322 
324  const trajectory_msgs::JointTrajectoryConstPtr& traj,
325  std::vector<SimpleMessage>* msgs)
326 {
327  msgs->clear();
328 
329  // check for valid trajectory
330  if (!is_valid(*traj))
331  return false;
332 
333  for (size_t i = 0; i < traj->points.size(); ++i)
334  {
335  SimpleMessage msg;
336  ros_JointTrajPt rbt_pt, xform_pt;
337 
338  // select / reorder joints for sending to robot
339  if (!select(traj->joint_names, traj->points[i],
340  this->all_joint_names_, &rbt_pt))
341  return false;
342 
343  // transform point data (e.g. for joint-coupling)
344  if (!transform(rbt_pt, &xform_pt))
345  return false;
346 
347  // convert trajectory point to ROS message
348  if (!create_message(i, xform_pt, &msg))
349  return false;
350 
351  msgs->push_back(msg);
352  }
353 
354  return true;
355 }
356 
358  const std::vector<std::string>& ros_joint_names,
359  const ros_dynamicPoint& ros_pt,
360  const std::vector<std::string>& rbt_joint_names, ros_dynamicPoint* rbt_pt)
361 {
362  ROS_ASSERT(ros_joint_names.size() == ros_pt.positions.size());
363  // initialize rbt_pt
364  *rbt_pt = ros_pt;
365  rbt_pt->positions.clear();
366  rbt_pt->velocities.clear();
367  rbt_pt->accelerations.clear();
368 
369  for (size_t rbt_idx = 0; rbt_idx < rbt_joint_names.size(); ++rbt_idx)
370  {
371  bool is_empty = rbt_joint_names[rbt_idx].empty();
372 
373  // find matching ROS element
374  size_t ros_idx = std::find(ros_joint_names.begin(),
375  ros_joint_names.end(),
376  rbt_joint_names[rbt_idx]) - ros_joint_names.begin();
377  bool is_found = ros_idx < ros_joint_names.size();
378 
379 
380  // error-chk: required robot joint not found in ROS joint-list
381  if (!is_empty && !is_found)
382  {
383  ROS_ERROR("Expected joint (%s) not found in JointTrajectory.Aborting command.",
384  rbt_joint_names[rbt_idx].c_str());
385  return false;
386  }
387 
388  if (is_empty)
389  {
390  if (!ros_pt.positions.empty()) rbt_pt->positions.push_back(default_joint_pos_);
391  if (!ros_pt.velocities.empty()) rbt_pt->velocities.push_back(-1);
392  if (!ros_pt.accelerations.empty()) rbt_pt->accelerations.push_back(-1);
393  }
394  else
395  {
396  if (!ros_pt.positions.empty())
397  rbt_pt->positions.push_back(ros_pt.positions[ros_idx]);
398  if (!ros_pt.velocities.empty())
399  rbt_pt->velocities.push_back(ros_pt.velocities[ros_idx]);
400  if (!ros_pt.accelerations.empty())
401  rbt_pt->accelerations.push_back(ros_pt.accelerations[ros_idx]);
402  }
403  }
404  return true;
405 }
406 
407 
409  const std::vector<std::string>& ros_joint_names,
410  const ros_JointTrajPt& ros_pt, const std::vector<std::string>& rbt_joint_names,
411  ros_JointTrajPt* rbt_pt)
412 {
413  ROS_ASSERT(ros_joint_names.size() == ros_pt.positions.size());
414  // initialize rbt_pt
415  *rbt_pt = ros_pt;
416  rbt_pt->positions.clear();
417  rbt_pt->velocities.clear();
418  rbt_pt->accelerations.clear();
419 
420  for (size_t rbt_idx = 0; rbt_idx < rbt_joint_names.size(); ++rbt_idx)
421  {
422  bool is_empty = rbt_joint_names[rbt_idx].empty();
423 
424  // find matching ROS element
425  size_t ros_idx = std::find(ros_joint_names.begin(), ros_joint_names.end(),
426  rbt_joint_names[rbt_idx]) - ros_joint_names.begin();
427  bool is_found = ros_idx < ros_joint_names.size();
428 
429  // error-chk: required robot joint not found in ROS joint-list
430  if (!is_empty && !is_found)
431  {
432  ROS_ERROR("Expected joint (%s) not found in JointTrajectory. Aborting command.",
433  rbt_joint_names[rbt_idx].c_str());
434  return false;
435  }
436 
437  if (is_empty)
438  {
439  if (!ros_pt.positions.empty()) rbt_pt->positions.push_back(default_joint_pos_);
440  if (!ros_pt.velocities.empty()) rbt_pt->velocities.push_back(-1);
441  if (!ros_pt.accelerations.empty()) rbt_pt->accelerations.push_back(-1);
442  }
443  else
444  {
445  if (!ros_pt.positions.empty()) rbt_pt->positions.push_back(ros_pt.positions[ros_idx]);
446  if (!ros_pt.velocities.empty()) rbt_pt->velocities.push_back(ros_pt.velocities[ros_idx]);
447  if (!ros_pt.accelerations.empty()) rbt_pt->accelerations.push_back(ros_pt.accelerations[ros_idx]);
448  }
449  }
450  return true;
451 }
452 
453 // default velocity calculation computes the %-of-max-velocity for the "critical joint" (closest to velocity-limit)
454 // such that 0.2 = 20% of maximum joint speed.
455 //
456 // NOTE: this calculation uses the maximum joint speeds from the URDF file, which may differ from those defined on
457 // the physical robot. These differences could lead to different actual movement velocities than intended.
458 // Behavior should be verified on a physical robot if movement velocity is critical.
460  const trajectory_msgs::JointTrajectoryPoint& pt, double* rbt_velocity)
461 {
462  std::vector<double> vel_ratios;
463 
464  ROS_ASSERT(all_joint_names_.size() == pt.positions.size());
465 
466  // check for empty velocities in ROS topic
467  if (pt.velocities.empty())
468  {
469  ROS_WARN("Joint velocities unspecified. Using default/safe speed.");
470  *rbt_velocity = default_vel_ratio_;
471  return true;
472  }
473 
474  for (size_t i = 0; i < all_joint_names_.size(); ++i)
475  {
476  const std::string &jnt_name = all_joint_names_[i];
477 
478  // update vel_ratios
479  if (jnt_name.empty()) // ignore "dummy joints" in velocity calcs
480  vel_ratios.push_back(-1);
481  else if (joint_vel_limits_.count(jnt_name) == 0) // no velocity limit specified for this joint
482  vel_ratios.push_back(-1);
483  else
484  vel_ratios.push_back(
485  fabs(pt.velocities[i] / joint_vel_limits_[jnt_name])); // calculate expected duration for this joint
486  }
487 
488  // find largest velocity-ratio (closest to max joint-speed)
489  int max_idx = std::max_element(vel_ratios.begin(), vel_ratios.end()) - vel_ratios.begin();
490 
491  if (vel_ratios[max_idx] > 0)
492  *rbt_velocity = vel_ratios[max_idx];
493  else
494  {
495  ROS_WARN_ONCE("Joint velocity-limits unspecified. Using default velocity-ratio.");
496  *rbt_velocity = default_vel_ratio_;
497  }
498 
499  if ((*rbt_velocity < 0) || (*rbt_velocity > 1))
500  {
501  ROS_WARN("computed velocity (%.1f %%) is out-of-range. Clipping to [0-100%%]", *rbt_velocity * 100);
502  *rbt_velocity = std::min(1.0, std::max(0.0, *rbt_velocity)); // clip to [0,1]
503  }
504 
505  return true;
506 }
507 
508 bool JointTrajectoryInterface::calc_velocity(const motoman_msgs::DynamicJointsGroup& pt, double* rbt_velocity)
509 {
510  std::vector<double> vel_ratios;
511 
512  // check for empty velocities in ROS topic
513  if (pt.velocities.empty())
514  {
515  ROS_WARN("Joint velocities unspecified. Using default/safe speed.");
516  *rbt_velocity = default_vel_ratio_;
517  return true;
518  }
519 
520  robot_groups_[pt.group_number].get_joint_names();
521  for (size_t i = 0; i < robot_groups_[pt.group_number].get_joint_names().size(); ++i)
522  {
523  const std::string &jnt_name = robot_groups_[pt.group_number].get_joint_names()[i];
524 
525  // update vel_ratios
526  if (jnt_name.empty()) // ignore "dummy joints" in velocity calcs
527  vel_ratios.push_back(-1);
528  else if (joint_vel_limits_.count(jnt_name) == 0) // no velocity limit specified for this joint
529  vel_ratios.push_back(-1);
530  else
531  vel_ratios.push_back(
532  fabs(pt.velocities[i] / joint_vel_limits_[jnt_name])); // calculate expected duration for this joint
533  }
534 
535  // find largest velocity-ratio (closest to max joint-speed)
536  int max_idx = std::max_element(vel_ratios.begin(), vel_ratios.end()) - vel_ratios.begin();
537 
538  if (vel_ratios[max_idx] > 0)
539  *rbt_velocity = vel_ratios[max_idx];
540  else
541  {
542  ROS_WARN_ONCE("Joint velocity-limits unspecified. Using default velocity-ratio.");
543  *rbt_velocity = default_vel_ratio_;
544  }
545 
546  if ((*rbt_velocity < 0) || (*rbt_velocity > 1))
547  {
548  ROS_WARN("computed velocity (%.1f %%) is out-of-range. Clipping to [0-100%%]", *rbt_velocity * 100);
549  *rbt_velocity = std::min(1.0, std::max(0.0, *rbt_velocity)); // clip to [0,1]
550  }
551 
552  return true;
553 }
554 
556 (const trajectory_msgs::JointTrajectoryPoint& pt, double* rbt_duration)
557 {
558  std::vector<double> durations;
559  double this_time = pt.time_from_start.toSec();
560  static double last_time = 0;
561 
562  if (this_time <= last_time) // earlier time => new trajectory. Move slowly to first point.
563  *rbt_duration = default_duration_;
564  else
565  *rbt_duration = this_time - last_time;
566 
567  last_time = this_time;
568 
569  return true;
570 }
571 
573  const motoman_msgs::DynamicJointsGroup& pt, double* rbt_duration)
574 {
575  std::vector<double> durations;
576  double this_time = pt.time_from_start.toSec();
577  static double last_time = 0;
578 
579  if (this_time <= last_time) // earlier time => new trajectory. Move slowly to first point.
580  *rbt_duration = default_duration_;
581  else
582  *rbt_duration = this_time - last_time;
583 
584  last_time = this_time;
585 
586  return true;
587 }
588 
590  int seq, const motoman_msgs::DynamicJointsGroup &pt, SimpleMessage *msg)
591 {
593 
594  for (size_t i = 0; i < pt.positions.size(); ++i)
595  {
596  pos.setJoint(i, pt.positions[i]);
597  }
598 
599  // calculate velocity & duration
600  double velocity, duration;
601  if (!calc_velocity(pt, &velocity) || !calc_duration(pt, &duration))
602  return false;
603 
604  rbt_JointTrajPt msg_data;
605  msg_data.init(seq, pos, velocity, duration);
606 
607  JointTrajPtMessage jtp_msg;
608  jtp_msg.init(msg_data);
609 
610  return jtp_msg.toTopic(*msg); // assume "topic" COMM_TYPE for now
611 }
612 
613 bool JointTrajectoryInterface::create_message_ex(
614  int seq, const motoman_msgs::DynamicJointPoint &pt, SimpleMessage *msg)
615 {
616  return true;
617 }
618 
620  int seq, const trajectory_msgs::JointTrajectoryPoint &pt, SimpleMessage *msg)
621 {
623  ROS_ASSERT(pt.positions.size() <= (unsigned int)pos.getMaxNumJoints());
624 
625  for (size_t i = 0; i < pt.positions.size(); ++i)
626  pos.setJoint(i, pt.positions[i]);
627 
628  // calculate velocity & duration
629  double velocity, duration;
630  if (!calc_velocity(pt, &velocity) || !calc_duration(pt, &duration))
631  return false;
632 
633  rbt_JointTrajPt msg_data;
634  msg_data.init(seq, pos, velocity, duration);
635 
636  JointTrajPtMessage jtp_msg;
637  jtp_msg.init(msg_data);
638 
639  return jtp_msg.toTopic(*msg); // assume "topic" COMM_TYPE for now
640 }
641 
643 {
644  JointTrajPtMessage jMsg;
645  SimpleMessage msg, reply;
646 
647  ROS_INFO("Joint trajectory handler: entering stopping state");
648  jMsg.setSequence(SpecialSeqValues::STOP_TRAJECTORY);
649  jMsg.toRequest(msg);
650  ROS_DEBUG("Sending stop command");
651  this->connection_->sendAndReceiveMsg(msg, reply);
652 }
653 
655  industrial_msgs::StopMotion::Request &req,
656  industrial_msgs::StopMotion::Response &res)
657 {
658  trajectoryStop();
659 
660  // no success/fail result from trajectoryStop. Assume success.
661  res.code.val = industrial_msgs::ServiceReturnCode::SUCCESS;
662 
663  return true; // always return true. To distinguish between call-failed and service-unavailable.
664 }
665 
666 bool JointTrajectoryInterface::is_valid(const trajectory_msgs::JointTrajectory &traj)
667 {
668  for (size_t i = 0; i < traj.points.size(); ++i)
669  {
670  const trajectory_msgs::JointTrajectoryPoint &pt = traj.points[i];
671 
672  // check for non-empty positions
673  if (pt.positions.empty())
674  ROS_ERROR_RETURN(false, "Validation failed: Missing position data for trajectory pt %lu", i);
675 
676  // check for joint velocity limits
677  for (size_t j = 0; j < pt.velocities.size(); ++j)
678  {
679  std::map<std::string, double>::iterator max_vel = joint_vel_limits_.find(traj.joint_names[j]);
680  if (max_vel == joint_vel_limits_.end()) continue; // no velocity-checking if limit not defined
681 
682  if (std::abs(pt.velocities[j]) > max_vel->second)
683  ROS_ERROR_RETURN(false, "Validation failed: Max velocity exceeded for trajectory pt %lu, joint '%s'", i,
684  traj.joint_names[j].c_str());
685  }
686 
687  // check for valid timestamp
688  if ((i > 0) && (pt.time_from_start.toSec() == 0))
689  ROS_ERROR_RETURN(false, "Validation failed: Missing valid timestamp data for trajectory pt %lu", i);
690  }
691 
692  return true;
693 }
694 
695 bool JointTrajectoryInterface::is_valid(const motoman_msgs::DynamicJointTrajectory &traj)
696 {
697  for (size_t i = 0; i < traj.points.size(); ++i)
698  {
699  for (int gr = 0; gr < traj.points[i].num_groups; gr++)
700  {
701  const motoman_msgs::DynamicJointsGroup &pt = traj.points[i].groups[gr];
702 
703  // check for non-empty positions
704  if (pt.positions.empty())
705  ROS_ERROR_RETURN(false, "Validation failed: Missing position data for trajectory pt %lu", i);
706  // check for joint velocity limits
707  for (size_t j = 0; j < pt.velocities.size(); ++j)
708  {
709  std::map<std::string, double>::iterator max_vel = joint_vel_limits_.find(traj.joint_names[j]);
710  if (max_vel == joint_vel_limits_.end()) continue; // no velocity-checking if limit not defined
711 
712  if (std::abs(pt.velocities[j]) > max_vel->second)
713  ROS_ERROR_RETURN(false, "Validation failed: Max velocity exceeded for trajectory pt %lu, joint '%s'", i,
714  traj.joint_names[j].c_str());
715  }
716 
717  // check for valid timestamp
718  if ((i > 0) && (pt.time_from_start.toSec() == 0))
719  ROS_ERROR_RETURN(false, "Validation failed: Missing valid timestamp data for trajectory pt %lu", i);
720  }
721  }
722  return true;
723 }
724 
725 // copy robot JointState into local cache
727  const sensor_msgs::JointStateConstPtr &msg)
728 {
729  this->cur_joint_pos_ = *msg;
730 }
731 
733  const sensor_msgs::JointStateConstPtr &msg, int robot_id)
734 {
735  this->cur_joint_pos_map_[robot_id] = *msg;
736 }
737 
738 } // namespace joint_trajectory_interface
739 } // namespace industrial_robot_client
740 
float pos[ROS_MAX_JOINT]
bool init(char *buff, int port_num)
bool getJointNames(const std::string joint_list_param, const std::string urdf_param, std::vector< std::string > &joint_names)
#define ROS_ERROR_RETURN(rtn,...)
virtual bool calc_velocity(const trajectory_msgs::JointTrajectoryPoint &pt, double *rbt_velocity)
bool getJointGroups(const std::string topic_param, std::map< int, RobotGroup > &robot_groups)
Parses multi-group joints from topic_param.
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
virtual bool transform(const trajectory_msgs::JointTrajectoryPoint &pt_in, trajectory_msgs::JointTrajectoryPoint *pt_out)
virtual bool calc_duration(const trajectory_msgs::JointTrajectoryPoint &pt, double *rbt_duration)
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
#define ROS_WARN(...)
virtual bool send_to_robot(const std::vector< JointTrajPtMessage > &messages)=0
bool sendAndReceiveMsg(industrial::simple_message::SimpleMessage &send, industrial::simple_message::SimpleMessage &recv, bool verbose=false)
static JointTrajPtMessage create_message(int seq, std::vector< double > joint_pos, double velocity, double duration)
#define ROS_WARN_ONCE(...)
#define ROS_INFO(...)
bool setJoint(industrial::shared_types::shared_int index, industrial::shared_types::shared_real value)
virtual void jointTrajectoryCB(const trajectory_msgs::JointTrajectoryConstPtr &msg)
virtual bool init(std::string default_ip="", int default_port=StandardSocketPorts::MOTION)
virtual bool select(const std::vector< std::string > &ros_joint_names, const trajectory_msgs::JointTrajectoryPoint &ros_pt, const std::vector< std::string > &rbt_joint_names, trajectory_msgs::JointTrajectoryPoint *rbt_pt)
bool getJointVelocityLimits(const std::string urdf_param_name, std::map< std::string, double > &velocity_limits)
motoman_msgs::DynamicJointsGroup ros_dynamicPoint
trajectory_msgs::JointTrajectoryPoint ros_JointTrajPt
virtual bool stopMotionCB(industrial_msgs::StopMotion::Request &req, industrial_msgs::StopMotion::Response &res)
#define ROS_ASSERT(cond)
#define ROS_ERROR(...)
industrial::joint_traj_pt::JointTrajPt rbt_JointTrajPt
virtual bool trajectory_to_msgs(const trajectory_msgs::JointTrajectoryConstPtr &traj, std::vector< JointTrajPtMessage > *msgs)
#define ROS_DEBUG(...)


motoman_driver
Author(s): Jeremy Zoss (Southwest Research Institute), Ted Miller (MotoROS) (Yaskawa Motoman), Eric Marcil (MotoROS) (Yaskawa Motoman)
autogenerated on Sat May 8 2021 02:27:43