00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <algorithm>
00033 #include "motoman_driver/industrial_robot_client/joint_trajectory_interface.h"
00034 #include "motoman_driver/industrial_robot_client/motoman_utils.h"
00035 #include "simple_message/joint_traj_pt.h"
00036 #include "industrial_utils/param_utils.h"
00037 #include <vector>
00038 #include <map>
00039 #include <string>
00040
00041 using industrial_utils::param::getJointNames;
00042 using industrial_robot_client::motoman_utils::getJointGroups;
00043 using industrial::simple_message::SimpleMessage;
00044 namespace SpecialSeqValues = industrial::joint_traj_pt::SpecialSeqValues;
00045 typedef industrial::joint_traj_pt::JointTrajPt rbt_JointTrajPt;
00046 typedef trajectory_msgs::JointTrajectoryPoint ros_JointTrajPt;
00047 typedef motoman_msgs::DynamicJointsGroup ros_dynamicPoint;
00048
00049 namespace industrial_robot_client
00050 {
00051 namespace joint_trajectory_interface
00052 {
00053
00054 #define ROS_ERROR_RETURN(rtn,...) do {ROS_ERROR(__VA_ARGS__); return(rtn);} while(0)
00055
00056 bool JointTrajectoryInterface::init(std::string default_ip, int default_port, bool version_0)
00057 {
00058 std::string ip;
00059 int port;
00060
00061
00062 ros::param::param<std::string>("robot_ip_address", ip, default_ip);
00063 ros::param::param<int>("~port", port, default_port);
00064
00065
00066 if (ip.empty())
00067 {
00068 ROS_ERROR("No valid robot IP address found. Please set ROS 'robot_ip_address' param");
00069 return false;
00070 }
00071 if (port <= 0)
00072 {
00073 ROS_ERROR("No valid robot TCP port found. Please set ROS '~port' param");
00074 return false;
00075 }
00076
00077 char* ip_addr = strdup(ip.c_str());
00078 ROS_INFO("Joint Trajectory Interface connecting to IP address: '%s:%d'", ip_addr, port);
00079 default_tcp_connection_.init(ip_addr, port);
00080 free(ip_addr);
00081
00082 return init(&default_tcp_connection_);
00083 }
00084
00085 bool JointTrajectoryInterface::init(SmplMsgConnection* connection)
00086 {
00087 std::map<int, RobotGroup> robot_groups;
00088 if(getJointGroups("topic_list", robot_groups))
00089 {
00090 this->version_0_ = false;
00091 return init(connection, robot_groups);
00092 }
00093 else
00094 {
00095 this->version_0_ = true;
00096 std::vector<std::string> joint_names;
00097 if (!getJointNames("controller_joint_names", "robot_description", joint_names))
00098 {
00099 ROS_WARN("Unable to read 'controller_joint_names' param. Using standard 6-DOF joint names.");
00100 }
00101 return init(connection, joint_names);
00102 }
00103 return false;
00104 }
00105
00106 bool JointTrajectoryInterface::init(SmplMsgConnection* connection, const std::vector<std::string> &joint_names,
00107 const std::map<std::string, double> &velocity_limits)
00108 {
00109 this->connection_ = connection;
00110 this->all_joint_names_ = joint_names;
00111 this->joint_vel_limits_ = velocity_limits;
00112 connection_->makeConnect();
00113
00114
00115 if (joint_vel_limits_.empty()
00116 && !industrial_utils::param::getJointVelocityLimits("robot_description", joint_vel_limits_))
00117 ROS_WARN("Unable to read velocity limits from 'robot_description' param. Velocity validation disabled.");
00118
00119
00120 this->srv_stop_motion_ = this->node_.advertiseService(
00121 "stop_motion", &JointTrajectoryInterface::stopMotionCB, this);
00122 this->srv_joint_trajectory_ = this->node_.advertiseService(
00123 "joint_path_command", &JointTrajectoryInterface::jointTrajectoryCB, this);
00124 this->sub_joint_trajectory_ = this->node_.subscribe(
00125 "joint_path_command", 0, &JointTrajectoryInterface::jointTrajectoryCB, this);
00126 this->sub_cur_pos_ = this->node_.subscribe(
00127 "joint_states", 1, &JointTrajectoryInterface::jointStateCB, this);
00128
00129 return true;
00130 }
00131
00132 bool JointTrajectoryInterface::init(
00133 SmplMsgConnection* connection, const std::map<int, RobotGroup> &robot_groups,
00134 const std::map<std::string, double> &velocity_limits)
00135 {
00136 this->connection_ = connection;
00137 this->robot_groups_ = robot_groups;
00138 this->joint_vel_limits_ = velocity_limits;
00139 connection_->makeConnect();
00140
00141
00142 if (joint_vel_limits_.empty()
00143 && !industrial_utils::param::getJointVelocityLimits(
00144 "robot_description", joint_vel_limits_))
00145 ROS_WARN("Unable to read velocity limits from 'robot_description' param. Velocity validation disabled.");
00146
00147
00148 this->srv_joint_trajectory_ = this->node_.advertiseService(
00149 "joint_path_command", &JointTrajectoryInterface::jointTrajectoryExCB, this);
00150 this->sub_joint_trajectory_ = this->node_.subscribe(
00151 "joint_path_command", 0, &JointTrajectoryInterface::jointTrajectoryExCB, this);
00152 this->srv_stop_motion_ = this->node_.advertiseService(
00153 "stop_motion", &JointTrajectoryInterface::stopMotionCB, this);
00154
00155 for (it_type iterator = this->robot_groups_.begin(); iterator != this->robot_groups_.end(); iterator++)
00156 {
00157 std::string name_str, ns_str;
00158 int robot_id = iterator->first;
00159 name_str = iterator->second.get_name();
00160 ns_str = iterator->second.get_ns();
00161
00162 ros::ServiceServer srv_joint_trajectory;
00163 ros::ServiceServer srv_stop_motion;
00164 ros::Subscriber sub_joint_trajectory;
00165
00166 srv_stop_motion = this->node_.advertiseService(
00167 ns_str + "/" + name_str + "/stop_motion",
00168 &JointTrajectoryInterface::stopMotionCB, this);
00169 srv_joint_trajectory = this->node_.advertiseService(
00170 ns_str + "/" + name_str + "/joint_path_command",
00171 &JointTrajectoryInterface::jointTrajectoryExCB, this);
00172 sub_joint_trajectory = this->node_.subscribe(
00173 ns_str + "/" + name_str + "/joint_path_command", 0,
00174 &JointTrajectoryInterface::jointTrajectoryExCB, this);
00175
00176 this->srv_stops_[robot_id] = srv_stop_motion;
00177 this->srv_joints_[robot_id] = srv_joint_trajectory;
00178 this->sub_joint_trajectories_[robot_id] = sub_joint_trajectory;
00179
00180 this->sub_cur_pos_ = this->node_.subscribe<sensor_msgs::JointState>(
00181 ns_str + "/" + name_str + "/joint_states", 1,
00182 boost::bind(&JointTrajectoryInterface::jointStateCB, this, _1, robot_id));
00183
00184 this->sub_cur_positions_[robot_id] = this->sub_cur_pos_;
00185 }
00186
00187
00188 return true;
00189 }
00190
00191 JointTrajectoryInterface::~JointTrajectoryInterface()
00192 {
00193 trajectoryStop();
00194 this->sub_joint_trajectory_.shutdown();
00195 }
00196
00197 bool JointTrajectoryInterface::jointTrajectoryExCB(
00198 motoman_msgs::CmdJointTrajectoryEx::Request &req,
00199 motoman_msgs::CmdJointTrajectoryEx::Response &res)
00200 {
00201 motoman_msgs::DynamicJointTrajectoryPtr traj_ptr(
00202 new motoman_msgs::DynamicJointTrajectory);
00203 *traj_ptr = req.trajectory;
00204 this->jointTrajectoryExCB(traj_ptr);
00205
00206
00207 res.code.val = industrial_msgs::ServiceReturnCode::SUCCESS;
00208
00209 return true;
00210 }
00211
00212
00213 bool JointTrajectoryInterface::jointTrajectoryCB(
00214 industrial_msgs::CmdJointTrajectory::Request &req,
00215 industrial_msgs::CmdJointTrajectory::Response &res)
00216 {
00217 trajectory_msgs::JointTrajectoryPtr traj_ptr(
00218 new trajectory_msgs::JointTrajectory);
00219 *traj_ptr = req.trajectory;
00220 this->jointTrajectoryCB(traj_ptr);
00221
00222 res.code.val = industrial_msgs::ServiceReturnCode::SUCCESS;
00223
00224 return true;
00225 }
00226
00227 void JointTrajectoryInterface::jointTrajectoryExCB(
00228 const motoman_msgs::DynamicJointTrajectoryConstPtr &msg)
00229 {
00230 ROS_INFO("Receiving joint trajectory message Dynamic");
00231
00232
00233 if (msg->points.empty())
00234 {
00235 ROS_INFO("Empty trajectory received, canceling current trajectory");
00236 trajectoryStop();
00237 return;
00238 }
00239
00240
00241 std::vector<SimpleMessage> robot_msgs;
00242 if (!trajectory_to_msgs(msg, &robot_msgs))
00243 return;
00244
00245
00246 send_to_robot(robot_msgs);
00247 }
00248
00249
00250 void JointTrajectoryInterface::jointTrajectoryCB(
00251 const trajectory_msgs::JointTrajectoryConstPtr &msg)
00252 {
00253 ROS_INFO("Receiving joint trajectory message");
00254
00255
00256 if (msg->points.empty())
00257 {
00258 ROS_INFO("Empty trajectory received, canceling current trajectory");
00259 trajectoryStop();
00260 return;
00261 }
00262
00263
00264 std::vector<SimpleMessage> robot_msgs;
00265 if (!trajectory_to_msgs(msg, &robot_msgs))
00266 return;
00267
00268
00269 send_to_robot(robot_msgs);
00270 }
00271
00272 bool JointTrajectoryInterface::trajectory_to_msgs(
00273 const motoman_msgs::DynamicJointTrajectoryConstPtr& traj,
00274 std::vector<SimpleMessage>* msgs)
00275 {
00276 msgs->clear();
00277
00278 std::vector<double>::iterator it;
00279
00280 if (traj->points[0].num_groups == 1)
00281 {
00282
00283 if (!is_valid(*traj))
00284 {
00285 return false;
00286 }
00287
00288 for (size_t i = 0; i < traj->points.size(); ++i)
00289 {
00290 SimpleMessage msg;
00291 ros_dynamicPoint rbt_pt, xform_pt;
00292
00293
00294 if (!select(traj->joint_names, traj->points[i].groups[0],
00295 robot_groups_[traj->points[i].groups[0].group_number].get_joint_names(),
00296 &rbt_pt))
00297 return false;
00298
00299
00300 if (!transform(rbt_pt, &xform_pt))
00301 return false;
00302
00303
00304 if (!create_message(i, xform_pt, &msg))
00305 return false;
00306
00307 msgs->push_back(msg);
00308 }
00309 }
00310
00311 else if (traj->points[0].num_groups <= 4)
00312 {
00313 for (size_t i = 0; i < traj->points.size(); ++i)
00314 {
00315 SimpleMessage msg;
00316 create_message_ex(i, traj->points[i], &msg);
00317 msgs->push_back(msg);
00318 }
00319 }
00320 return true;
00321 }
00322
00323 bool JointTrajectoryInterface::trajectory_to_msgs(
00324 const trajectory_msgs::JointTrajectoryConstPtr& traj,
00325 std::vector<SimpleMessage>* msgs)
00326 {
00327 msgs->clear();
00328
00329
00330 if (!is_valid(*traj))
00331 return false;
00332
00333 for (size_t i = 0; i < traj->points.size(); ++i)
00334 {
00335 SimpleMessage msg;
00336 ros_JointTrajPt rbt_pt, xform_pt;
00337
00338
00339 if (!select(traj->joint_names, traj->points[i],
00340 this->all_joint_names_, &rbt_pt))
00341 return false;
00342
00343
00344 if (!transform(rbt_pt, &xform_pt))
00345 return false;
00346
00347
00348 if (!create_message(i, xform_pt, &msg))
00349 return false;
00350
00351 msgs->push_back(msg);
00352 }
00353
00354 return true;
00355 }
00356
00357 bool JointTrajectoryInterface::select(
00358 const std::vector<std::string>& ros_joint_names,
00359 const ros_dynamicPoint& ros_pt,
00360 const std::vector<std::string>& rbt_joint_names, ros_dynamicPoint* rbt_pt)
00361 {
00362 ROS_ASSERT(ros_joint_names.size() == ros_pt.positions.size());
00363
00364 *rbt_pt = ros_pt;
00365 rbt_pt->positions.clear();
00366 rbt_pt->velocities.clear();
00367 rbt_pt->accelerations.clear();
00368
00369 for (size_t rbt_idx = 0; rbt_idx < rbt_joint_names.size(); ++rbt_idx)
00370 {
00371 bool is_empty = rbt_joint_names[rbt_idx].empty();
00372
00373
00374 size_t ros_idx = std::find(ros_joint_names.begin(),
00375 ros_joint_names.end(),
00376 rbt_joint_names[rbt_idx]) - ros_joint_names.begin();
00377 bool is_found = ros_idx < ros_joint_names.size();
00378
00379
00380
00381 if (!is_empty && !is_found)
00382 {
00383 ROS_ERROR("Expected joint (%s) not found in JointTrajectory.Aborting command.",
00384 rbt_joint_names[rbt_idx].c_str());
00385 return false;
00386 }
00387
00388 if (is_empty)
00389 {
00390 if (!ros_pt.positions.empty()) rbt_pt->positions.push_back(default_joint_pos_);
00391 if (!ros_pt.velocities.empty()) rbt_pt->velocities.push_back(-1);
00392 if (!ros_pt.accelerations.empty()) rbt_pt->accelerations.push_back(-1);
00393 }
00394 else
00395 {
00396 if (!ros_pt.positions.empty())
00397 rbt_pt->positions.push_back(ros_pt.positions[ros_idx]);
00398 if (!ros_pt.velocities.empty())
00399 rbt_pt->velocities.push_back(ros_pt.velocities[ros_idx]);
00400 if (!ros_pt.accelerations.empty())
00401 rbt_pt->accelerations.push_back(ros_pt.accelerations[ros_idx]);
00402 }
00403 }
00404 return true;
00405 }
00406
00407
00408 bool JointTrajectoryInterface::select(
00409 const std::vector<std::string>& ros_joint_names,
00410 const ros_JointTrajPt& ros_pt, const std::vector<std::string>& rbt_joint_names,
00411 ros_JointTrajPt* rbt_pt)
00412 {
00413 ROS_ASSERT(ros_joint_names.size() == ros_pt.positions.size());
00414
00415 *rbt_pt = ros_pt;
00416 rbt_pt->positions.clear();
00417 rbt_pt->velocities.clear();
00418 rbt_pt->accelerations.clear();
00419
00420 for (size_t rbt_idx = 0; rbt_idx < rbt_joint_names.size(); ++rbt_idx)
00421 {
00422 bool is_empty = rbt_joint_names[rbt_idx].empty();
00423
00424
00425 size_t ros_idx = std::find(ros_joint_names.begin(), ros_joint_names.end(),
00426 rbt_joint_names[rbt_idx]) - ros_joint_names.begin();
00427 bool is_found = ros_idx < ros_joint_names.size();
00428
00429
00430 if (!is_empty && !is_found)
00431 {
00432 ROS_ERROR("Expected joint (%s) not found in JointTrajectory. Aborting command.",
00433 rbt_joint_names[rbt_idx].c_str());
00434 return false;
00435 }
00436
00437 if (is_empty)
00438 {
00439 if (!ros_pt.positions.empty()) rbt_pt->positions.push_back(default_joint_pos_);
00440 if (!ros_pt.velocities.empty()) rbt_pt->velocities.push_back(-1);
00441 if (!ros_pt.accelerations.empty()) rbt_pt->accelerations.push_back(-1);
00442 }
00443 else
00444 {
00445 if (!ros_pt.positions.empty()) rbt_pt->positions.push_back(ros_pt.positions[ros_idx]);
00446 if (!ros_pt.velocities.empty()) rbt_pt->velocities.push_back(ros_pt.velocities[ros_idx]);
00447 if (!ros_pt.accelerations.empty()) rbt_pt->accelerations.push_back(ros_pt.accelerations[ros_idx]);
00448 }
00449 }
00450 return true;
00451 }
00452
00453
00454
00455
00456
00457
00458
00459 bool JointTrajectoryInterface::calc_velocity(
00460 const trajectory_msgs::JointTrajectoryPoint& pt, double* rbt_velocity)
00461 {
00462 std::vector<double> vel_ratios;
00463
00464 ROS_ASSERT(all_joint_names_.size() == pt.positions.size());
00465
00466
00467 if (pt.velocities.empty())
00468 {
00469 ROS_WARN("Joint velocities unspecified. Using default/safe speed.");
00470 *rbt_velocity = default_vel_ratio_;
00471 return true;
00472 }
00473
00474 for (size_t i = 0; i < all_joint_names_.size(); ++i)
00475 {
00476 const std::string &jnt_name = all_joint_names_[i];
00477
00478
00479 if (jnt_name.empty())
00480 vel_ratios.push_back(-1);
00481 else if (joint_vel_limits_.count(jnt_name) == 0)
00482 vel_ratios.push_back(-1);
00483 else
00484 vel_ratios.push_back(fabs(pt.velocities[i] / joint_vel_limits_[jnt_name]));
00485 }
00486
00487
00488 int max_idx = std::max_element(vel_ratios.begin(), vel_ratios.end()) - vel_ratios.begin();
00489
00490 if (vel_ratios[max_idx] > 0)
00491 *rbt_velocity = vel_ratios[max_idx];
00492 else
00493 {
00494 ROS_WARN_ONCE("Joint velocity-limits unspecified. Using default velocity-ratio.");
00495 *rbt_velocity = default_vel_ratio_;
00496 }
00497
00498 if ((*rbt_velocity < 0) || (*rbt_velocity > 1))
00499 {
00500 ROS_WARN("computed velocity (%.1f %%) is out-of-range. Clipping to [0-100%%]", *rbt_velocity * 100);
00501 *rbt_velocity = std::min(1.0, std::max(0.0, *rbt_velocity));
00502 }
00503
00504 return true;
00505 }
00506
00507 bool JointTrajectoryInterface::calc_velocity(const motoman_msgs::DynamicJointsGroup& pt, double* rbt_velocity)
00508 {
00509 std::vector<double> vel_ratios;
00510
00511
00512 if (pt.velocities.empty())
00513 {
00514 ROS_WARN("Joint velocities unspecified. Using default/safe speed.");
00515 *rbt_velocity = default_vel_ratio_;
00516 return true;
00517 }
00518
00519 robot_groups_[pt.group_number].get_joint_names();
00520 for (size_t i = 0; i < robot_groups_[pt.group_number].get_joint_names().size(); ++i)
00521 {
00522 const std::string &jnt_name = robot_groups_[pt.group_number].get_joint_names()[i];
00523
00524
00525 if (jnt_name.empty())
00526 vel_ratios.push_back(-1);
00527 else if (joint_vel_limits_.count(jnt_name) == 0)
00528 vel_ratios.push_back(-1);
00529 else
00530 vel_ratios.push_back(fabs(pt.velocities[i] / joint_vel_limits_[jnt_name]));
00531 }
00532
00533
00534 int max_idx = std::max_element(vel_ratios.begin(), vel_ratios.end()) - vel_ratios.begin();
00535
00536 if (vel_ratios[max_idx] > 0)
00537 *rbt_velocity = vel_ratios[max_idx];
00538 else
00539 {
00540 ROS_WARN_ONCE("Joint velocity-limits unspecified. Using default velocity-ratio.");
00541 *rbt_velocity = default_vel_ratio_;
00542 }
00543
00544 if ((*rbt_velocity < 0) || (*rbt_velocity > 1))
00545 {
00546 ROS_WARN("computed velocity (%.1f %%) is out-of-range. Clipping to [0-100%%]", *rbt_velocity * 100);
00547 *rbt_velocity = std::min(1.0, std::max(0.0, *rbt_velocity));
00548 }
00549
00550 return true;
00551 }
00552
00553 bool JointTrajectoryInterface::calc_duration
00554 (const trajectory_msgs::JointTrajectoryPoint& pt, double* rbt_duration)
00555 {
00556 std::vector<double> durations;
00557 double this_time = pt.time_from_start.toSec();
00558 static double last_time = 0;
00559
00560 if (this_time <= last_time)
00561 *rbt_duration = default_duration_;
00562 else
00563 *rbt_duration = this_time - last_time;
00564
00565 last_time = this_time;
00566
00567 return true;
00568 }
00569
00570 bool JointTrajectoryInterface::calc_duration(
00571 const motoman_msgs::DynamicJointsGroup& pt, double* rbt_duration)
00572 {
00573 std::vector<double> durations;
00574 double this_time = pt.time_from_start.toSec();
00575 static double last_time = 0;
00576
00577 if (this_time <= last_time)
00578 *rbt_duration = default_duration_;
00579 else
00580 *rbt_duration = this_time - last_time;
00581
00582 last_time = this_time;
00583
00584 return true;
00585 }
00586
00587 bool JointTrajectoryInterface::create_message(
00588 int seq, const motoman_msgs::DynamicJointsGroup &pt, SimpleMessage *msg)
00589 {
00590 industrial::joint_data::JointData pos;
00591
00592 for (size_t i = 0; i < pt.positions.size(); ++i)
00593 {
00594 pos.setJoint(i, pt.positions[i]);
00595 }
00596
00597
00598 double velocity, duration;
00599 if (!calc_velocity(pt, &velocity) || !calc_duration(pt, &duration))
00600 return false;
00601
00602 rbt_JointTrajPt msg_data;
00603 msg_data.init(seq, pos, velocity, duration);
00604
00605 JointTrajPtMessage jtp_msg;
00606 jtp_msg.init(msg_data);
00607
00608 return jtp_msg.toTopic(*msg);
00609 }
00610
00611 bool JointTrajectoryInterface::create_message_ex(
00612 int seq, const motoman_msgs::DynamicJointPoint &pt, SimpleMessage *msg)
00613 {
00614 return true;
00615 }
00616
00617 bool JointTrajectoryInterface::create_message(
00618 int seq, const trajectory_msgs::JointTrajectoryPoint &pt, SimpleMessage *msg)
00619 {
00620 industrial::joint_data::JointData pos;
00621 ROS_ASSERT(pt.positions.size() <= (unsigned int)pos.getMaxNumJoints());
00622
00623 for (size_t i = 0; i < pt.positions.size(); ++i)
00624 pos.setJoint(i, pt.positions[i]);
00625
00626
00627 double velocity, duration;
00628 if (!calc_velocity(pt, &velocity) || !calc_duration(pt, &duration))
00629 return false;
00630
00631 rbt_JointTrajPt msg_data;
00632 msg_data.init(seq, pos, velocity, duration);
00633
00634 JointTrajPtMessage jtp_msg;
00635 jtp_msg.init(msg_data);
00636
00637 return jtp_msg.toTopic(*msg);
00638 }
00639
00640 void JointTrajectoryInterface::trajectoryStop()
00641 {
00642 JointTrajPtMessage jMsg;
00643 SimpleMessage msg, reply;
00644
00645 ROS_INFO("Joint trajectory handler: entering stopping state");
00646 jMsg.setSequence(SpecialSeqValues::STOP_TRAJECTORY);
00647 jMsg.toRequest(msg);
00648 ROS_DEBUG("Sending stop command");
00649 this->connection_->sendAndReceiveMsg(msg, reply);
00650 }
00651
00652 bool JointTrajectoryInterface::stopMotionCB(
00653 industrial_msgs::StopMotion::Request &req,
00654 industrial_msgs::StopMotion::Response &res)
00655 {
00656 trajectoryStop();
00657
00658
00659 res.code.val = industrial_msgs::ServiceReturnCode::SUCCESS;
00660
00661 return true;
00662 }
00663
00664 bool JointTrajectoryInterface::is_valid(const trajectory_msgs::JointTrajectory &traj)
00665 {
00666 for (int i = 0; i < traj.points.size(); ++i)
00667 {
00668 const trajectory_msgs::JointTrajectoryPoint &pt = traj.points[i];
00669
00670
00671 if (pt.positions.empty())
00672 ROS_ERROR_RETURN(false, "Validation failed: Missing position data for trajectory pt %d", i);
00673
00674
00675 for (int j = 0; j < pt.velocities.size(); ++j)
00676 {
00677 std::map<std::string, double>::iterator max_vel = joint_vel_limits_.find(traj.joint_names[j]);
00678 if (max_vel == joint_vel_limits_.end()) continue;
00679
00680 if (std::abs(pt.velocities[j]) > max_vel->second)
00681 ROS_ERROR_RETURN(false, "Validation failed: Max velocity exceeded for trajectory pt %d, joint '%s'", i, traj.joint_names[j].c_str());
00682 }
00683
00684
00685 if ((i > 0) && (pt.time_from_start.toSec() == 0))
00686 ROS_ERROR_RETURN(false, "Validation failed: Missing valid timestamp data for trajectory pt %d", i);
00687 }
00688
00689 return true;
00690 }
00691
00692 bool JointTrajectoryInterface::is_valid(const motoman_msgs::DynamicJointTrajectory &traj)
00693 {
00694 for (int i = 0; i < traj.points.size(); ++i)
00695 {
00696 for (int gr = 0; gr < traj.points[i].num_groups; gr++)
00697 {
00698 const motoman_msgs::DynamicJointsGroup &pt = traj.points[i].groups[gr];
00699
00700
00701 if (pt.positions.empty())
00702 ROS_ERROR_RETURN(false, "Validation failed: Missing position data for trajectory pt %d", i);
00703
00704 for (int j = 0; j < pt.velocities.size(); ++j)
00705 {
00706 std::map<std::string, double>::iterator max_vel = joint_vel_limits_.find(traj.joint_names[j]);
00707 if (max_vel == joint_vel_limits_.end()) continue;
00708
00709 if (std::abs(pt.velocities[j]) > max_vel->second)
00710 ROS_ERROR_RETURN(false, "Validation failed: Max velocity exceeded for trajectory pt %d, joint '%s'", i, traj.joint_names[j].c_str());
00711 }
00712
00713
00714 if ((i > 0) && (pt.time_from_start.toSec() == 0))
00715 ROS_ERROR_RETURN(false, "Validation failed: Missing valid timestamp data for trajectory pt %d", i);
00716 }
00717 }
00718 return true;
00719 }
00720
00721
00722 void JointTrajectoryInterface::jointStateCB(
00723 const sensor_msgs::JointStateConstPtr &msg)
00724 {
00725 this->cur_joint_pos_ = *msg;
00726 }
00727
00728 void JointTrajectoryInterface::jointStateCB(
00729 const sensor_msgs::JointStateConstPtr &msg, int robot_id)
00730 {
00731 this->cur_joint_pos_map_[robot_id] = *msg;
00732 }
00733
00734 }
00735 }
00736