point_head_action.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2016, RoboTiCan Inc.
5  * Copyright (c) 2008, Willow Garage, Inc.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/or other materials provided
17  * with the distribution.
18  * * Neither the name of the Willow Garage nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *********************************************************************/
35 
36 #include <ros/ros.h>
37 
38 #include <vector>
39 #include <boost/scoped_ptr.hpp>
40 #include <boost/thread/condition.hpp>
41 
43 #include <geometry_msgs/PoseStamped.h>
44 #include <geometry_msgs/PointStamped.h>
45 #include <geometry_msgs/Twist.h>
46 
47 #include <kdl/chainfksolver.hpp>
48 #include <kdl/chain.hpp>
49 #include <kdl/chainjnttojacsolver.hpp>
50 #include <kdl/frames.hpp>
51 #include "kdl/chainfksolverpos_recursive.hpp"
53 
54 #include "tf_conversions/tf_kdl.h"
56 #include <tf/message_filter.h>
57 #include <tf/transform_datatypes.h>
58 #include <tf/transform_listener.h>
59 
60 #include <sensor_msgs/JointState.h>
61 #include <std_msgs/Float32MultiArray.h>
62 #include <std_msgs/Int32.h>
63 
64 #include <urdf/model.h>
65 
66 #include <trajectory_msgs/JointTrajectory.h>
67 #include <pr2_controllers_msgs/PointHeadAction.h>
68 #include <pr2_controllers_msgs/QueryTrajectoryState.h>
69 #include <pr2_controllers_msgs/JointTrajectoryControllerState.h>
70 
71 
72 void printVector3(const char * label, tf::Vector3 v)
73 {
74  printf("%s % 7.3f % 7.3f % 7.3f\n", label, v.x(), v.y(), v.z() );
75 
76 }
77 
79 {
80 private:
83 
84  std::string node_name_;
85  std::string action_name_;
86  std::string root_;
87  std::string tip_;
88  std::string pan_link_;
90  std::string pointing_frame_;
92  std::vector< std::string> joint_names_;
93 
100 
103  GoalHandle active_goal_;
105  std::string pan_parent_;
107 
108  geometry_msgs::PointStamped target_;
112 
113  boost::scoped_ptr<KDL::ChainFkSolverPos> pose_solver_;
114  boost::scoped_ptr<KDL::ChainJntToJacSolver> jac_solver_;
115 
118 
119 public:
120 
122  node_name_(ros::this_node::getName())
123  , action_name_("point_head_action")
124  , nh_(node)
125  , pnh_("~")
126  , action_server_(nh_, action_name_.c_str(),
127  boost::bind(&ControlHead::goalCB, this, _1),
128  boost::bind(&ControlHead::cancelCB, this, _1), false)
129  , has_active_goal_(false)
130  {
131  pnh_.param("pan_link", pan_link_, std::string("head_pan_link"));
132  pnh_.param("default_pointing_frame", default_pointing_frame_, std::string("head_tilt_link"));
133  pnh_.param("success_angle_threshold", success_angle_threshold_, 0.1);
134 
135  if(pan_link_[0] == '/') pan_link_.erase(0, 1);
136  if(default_pointing_frame_[0] == '/') default_pointing_frame_.erase(0, 1);
137 
138  // Connects to the controller
139  pub_controller_command_ =
140  nh_.advertise<trajectory_msgs::JointTrajectory>("command", 2);
141  sub_controller_state_ =
142  nh_.subscribe("state", 1, &ControlHead::controllerStateCB, this);
143  cli_query_traj_ =
144  nh_.serviceClient<pr2_controllers_msgs::QueryTrajectoryState>("/pan_tilt_trajectory_controller/query_state");
145 
146  // Should only ever happen on first call... move to constructor?
147  if(tree_.getNrOfJoints() == 0)
148  {
149  std::string robot_desc_string;
150  nh_.param("/robot_description", robot_desc_string, std::string());
151  ROS_DEBUG("Reading tree from robot_description...");
152  if (!kdl_parser::treeFromString(robot_desc_string, tree_)){
153  ROS_ERROR("Failed to construct kdl tree");
154  exit(-1);
155  }
156  if (!urdf_model_.initString(robot_desc_string)){
157  ROS_ERROR("Failed to parse urdf string for urdf::Model.");
158  exit(-2);
159  }
160  }
161 
162  ROS_DEBUG("Tree has %d joints and %d segments.", tree_.getNrOfJoints(), tree_.getNrOfSegments());
163 
164  action_server_.start();
165 
166  watchdog_timer_ = nh_.createTimer(ros::Duration(1.0), &ControlHead::watchdog, this);
167  }
168 
169  void goalCB(GoalHandle gh)
170  {
171  // Before we do anything, we need to know that name of the pan_link's parent, which we will treat as the root.
172  if (root_.empty())
173  {
174  for (int i = 0; i < 10; ++i)
175  {
176  try {
177  tfl_.getParent(pan_link_, ros::Time(), root_);
178  break;
179  }
180  catch (const tf::TransformException &ex) {}
181  ros::Duration(0.5).sleep();
182  }
183  if (root_.empty())
184  {
185  ROS_ERROR("Could not get parent of %s in the TF tree", pan_link_.c_str());
186  gh.setRejected();
187  return;
188  }
189  }
190  if(root_[0] == '/') root_.erase(0, 1);
191 
192  ROS_DEBUG("Got point head goal!");
193 
194  // Process pointing frame and axis
195  const geometry_msgs::PointStamped &target = gh.getGoal()->target;
196  pointing_frame_ = gh.getGoal()->pointing_frame;
197  if(pointing_frame_.length() == 0)
198  {
199  ROS_WARN("Pointing frame not specified, using %s [1, 0, 0] by default.", default_pointing_frame_.c_str());
200  pointing_frame_ = default_pointing_frame_;
201  pointing_axis_ = tf::Vector3(1.0, 0.0, 0.0);
202  }
203  else
204  {
205  if(pointing_frame_[0] == '/') pointing_frame_.erase(0, 1);
206  bool ret1 = false;
207  try
208  {
209  std::string error_msg;
210  ret1 = tfl_.waitForTransform(pan_link_, pointing_frame_, target.header.stamp,
211  ros::Duration(5.0), ros::Duration(0.01), &error_msg);
212 
213  tf::vector3MsgToTF(gh.getGoal()->pointing_axis, pointing_axis_);
214  if(pointing_axis_.length() < 0.1)
215  {
216  size_t found = pointing_frame_.find("optical_frame");
217  if (found != std::string::npos)
218  {
219  ROS_WARN("Pointing axis appears to be zero-length. Using [0, 0, 1] as default for an optical frame.");
220  pointing_axis_ = tf::Vector3(0, 0, 1);
221  }
222  else
223  {
224  ROS_WARN("Pointing axis appears to be zero-length. Using [1, 0, 0] as default for a non-optical frame.");
225  pointing_axis_ = tf::Vector3(1, 0, 0);
226  }
227  }
228  else
229  {
230  pointing_axis_.normalize();
231  }
232  }
233  catch(const tf::TransformException &ex)
234  {
235  ROS_ERROR("Transform failure (%d): %s", ret1, ex.what());
236  gh.setRejected();
237  return;
238  }
239  }
240 
241  //Put the target point in the root frame (usually torso_lift_link).
242  bool ret1 = false;
243  try
244  {
245  std::string error_msg;
246  ret1 = tfl_.waitForTransform(root_.c_str(), target.header.frame_id, target.header.stamp,
247  ros::Duration(5.0), ros::Duration(0.01), &error_msg);
248 
249  geometry_msgs::PointStamped target_in_root_msg;
250  tfl_.transformPoint(root_.c_str(), target, target_in_root_msg );
251  tf::pointMsgToTF(target_in_root_msg.point, target_in_root_);
252  }
253  catch(const tf::TransformException &ex)
254  {
255  ROS_ERROR("Transform failure (%d): %s", ret1, ex.what());
256  gh.setRejected();
257  return;
258  }
259 
260  if( tip_.compare(pointing_frame_) != 0 )
261  {
262  bool success = tree_.getChain(root_.c_str(), pointing_frame_.c_str(), chain_);
263  if( !success )
264  {
265  ROS_ERROR("Couldn't create chain from %s to %s.", root_.c_str(), pointing_frame_.c_str());
266  gh.setRejected();
267  return;
268  }
269  tip_ = pointing_frame_;
270 
271  pose_solver_.reset(new KDL::ChainFkSolverPos_recursive(chain_));
272  jac_solver_.reset(new KDL::ChainJntToJacSolver(chain_));
273  joint_names_.resize(chain_.getNrOfJoints());
274  }
275 
276  unsigned int joints = chain_.getNrOfJoints();
277 
278 // int segments = chain_.getNrOfSegments();
279 // ROS_INFO("Parsed urdf from %s to %s and found %d joints and %d segments.", root_.c_str(), pointing_frame_.c_str(), joints, segments);
280 // for(int i = 0; i < segments; i++)
281 // {
282 // KDL::Segment segment = chain_.getSegment(i);
283 // ROS_INFO("Segment %d, %s: joint %s type %s",
284 // i, segment.getName().c_str(), segment.getJoint().getName().c_str(), segment.getJoint().getTypeName().c_str() );
285 // }
286 
287  KDL::JntArray jnt_pos(joints), jnt_eff(joints);
288  KDL::Jacobian jacobian(joints);
289 
290  pr2_controllers_msgs::QueryTrajectoryState traj_state;
291  traj_state.request.time = ros::Time::now() + ros::Duration(0.01);
292  if (!cli_query_traj_.call(traj_state))
293  {
294  ROS_ERROR("Service call to query controller trajectory failed.");
295  gh.setRejected();
296  return;
297  }
298  if(traj_state.response.name.size() != joints)
299  {
300  ROS_ERROR("Number of joints mismatch: urdf chain vs. trajectory controller state.");
301  gh.setRejected();
302  return;
303  }
304  std::vector<urdf::JointLimits> limits_(joints);
305 
306  // Get initial joint positions and joint limits.
307  for(unsigned int i = 0; i < joints; i++)
308  {
309  joint_names_[i] = traj_state.response.name[i];
310  limits_[i] = *(urdf_model_.joints_[joint_names_[i].c_str()]->limits);
311  ROS_DEBUG("Joint %d %s: %f, limits: %f %f", i, traj_state.response.name[i].c_str(), traj_state.response.position[i], limits_[i].lower, limits_[i].upper);
312  //jnt_pos(i) = traj_state.response.position[i];
313  jnt_pos(i) = 0;
314  }
315 
316  int count = 0;
317  int limit_flips = 0;
318  float correction_angle = 2*M_PI;
319  float correction_delta = 2*M_PI;
320  while( ros::ok() && fabs(correction_delta) > 0.001)
321  {
322  //get the pose and jacobian for the current joint positions
323  KDL::Frame pose;
324  pose_solver_->JntToCart(jnt_pos, pose);
325  jac_solver_->JntToJac(jnt_pos, jacobian);
326 
327  tf::Transform frame_in_root;
328  tf::poseKDLToTF(pose, frame_in_root);
329 
330  tf::Vector3 axis_in_frame = pointing_axis_.normalized();
331  tf::Vector3 target_from_frame = (target_in_root_ - frame_in_root.getOrigin()).normalized();
332  tf::Vector3 current_in_frame = frame_in_root.getBasis().inverse()*target_from_frame;
333  float prev_correction = correction_angle;
334  correction_angle = current_in_frame.angle(axis_in_frame);
335  correction_delta = correction_angle - prev_correction;
336  ROS_DEBUG("At step %d, joint poses are %.4f and %.4f, angle error is %f", count, jnt_pos(0), jnt_pos(1), correction_angle);
337  if(correction_angle < 0.5*success_angle_threshold_) break;
338  tf::Vector3 correction_axis = frame_in_root.getBasis()*(axis_in_frame.cross(current_in_frame).normalized());
339  //printVector3("correction_axis in root:", correction_axis);
340  tf::Transform correction_tf(tf::Quaternion(correction_axis, 0.5*correction_angle), tf::Vector3(0,0,0));
341  KDL::Frame correction_kdl;
342  tf::transformTFToKDL(correction_tf, correction_kdl);
343 
344  // We apply a "wrench" proportional to the desired correction
345  KDL::Frame identity_kdl;
346  KDL::Twist twist = diff(correction_kdl, identity_kdl);
347  KDL::Wrench wrench_desi;
348  for (unsigned int i=0; i<6; i++)
349  wrench_desi(i) = -1.0*twist(i);
350 
351  // Converts the "wrench" into "joint corrections" with a jacbobian-transpose
352  for (unsigned int i = 0; i < joints; i++)
353  {
354  jnt_eff(i) = 0;
355  for (unsigned int j=0; j<6; j++)
356  jnt_eff(i) += (jacobian(j,i) * wrench_desi(j));
357  jnt_pos(i) += jnt_eff(i);
358  }
359 
360  // account for pan_link joint limit in back.
361  // if(jnt_pos(0) < limits_[0].lower && limit_flips++ == 0){ jnt_pos(0) += 1.5*M_PI; }
362  // if(jnt_pos(0) > limits_[0].upper && limit_flips++ == 0){ jnt_pos(0) -= 1.5*M_PI; }
363  for (unsigned int i = 0; i < joints; i++)
364  {
365  jnt_pos(i) = std::max(limits_[i].lower, jnt_pos(i));
366  jnt_pos(i) = std::min(limits_[i].upper, jnt_pos(i));
367  }
368 
369  // jnt_pos(1) = std::max(limits_[1].lower, jnt_pos(1));
370  // jnt_pos(1) = std::min(limits_[1].upper, jnt_pos(1));
371 
372  count++;
373 
374  if(limit_flips > 1){
375  ROS_ERROR("Goal is out of joint limits, trying to point there anyway... \n");
376  break;
377  }
378  }
379  ROS_DEBUG("Iterative solver took %d steps", count);
380 
381  std::vector<double> q_goal(joints);
382 
383  for(unsigned int i = 0; i < joints; i++)
384  {
385  jnt_pos(i) = std::max(limits_[i].lower, jnt_pos(i));
386  jnt_pos(i) = std::min(limits_[i].upper, jnt_pos(i));
387  q_goal[i] = jnt_pos(i);
388  ROS_DEBUG("Joint %d %s: %f", i, joint_names_[i].c_str(), jnt_pos(i));
389  }
390 
391  if (has_active_goal_)
392  {
393  active_goal_.setCanceled();
394  has_active_goal_ = false;
395  }
396 
397  gh.setAccepted();
398  active_goal_ = gh;
399  has_active_goal_ = true;
400 
401 
402  // Computes the duration of the movement.
403  ros::Duration min_duration(0.1);
404 
405  if (gh.getGoal()->min_duration > min_duration)
406  min_duration = gh.getGoal()->min_duration;
407 
408  // Determines if we need to increase the duration of the movement in order to enforce a maximum velocity.
409  if (gh.getGoal()->max_velocity > 0)
410  {
411  // Very approximate velocity limiting.
412  double dist = sqrt(pow(q_goal[0] - traj_state.response.position[0], 2) +
413  pow(q_goal[1] - traj_state.response.position[1], 2));
414  ros::Duration limit_from_velocity(dist / gh.getGoal()->max_velocity);
415  if (limit_from_velocity > min_duration)
416  min_duration = limit_from_velocity;
417  }
418 
419 
420  // Computes the command to send to the trajectory controller.
421  trajectory_msgs::JointTrajectory traj;
422  traj.header.stamp = traj_state.request.time;
423 
424  traj.joint_names.push_back(traj_state.response.name[0]);
425  traj.joint_names.push_back(traj_state.response.name[1]);
426 
427  traj.points.resize(1);
428  // traj.points[0].positions = traj_state.response.position;
429  //traj.points[0].velocities = traj_state.response.velocity;
430  //traj.points[0].time_from_start = ros::Duration(0.0);
431  traj.points[0].positions = q_goal;
432  traj.points[0].velocities.push_back(0);
433  traj.points[0].velocities.push_back(0);
434  traj.points[0].time_from_start = ros::Duration(min_duration);
435 
436  pub_controller_command_.publish(traj);
437  }
438 
439 
440  void watchdog(const ros::TimerEvent &e)
441  {
442  ros::Time now = ros::Time::now();
443 
444  // Aborts the active goal if the controller does not appear to be active.
445  if (has_active_goal_)
446  {
447  bool should_abort = false;
449  {
450  should_abort = true;
451  ROS_WARN("Aborting goal because we have never heard a controller state message.");
452  }
453  else if ((now - last_controller_state_->header.stamp) > ros::Duration(5.0))
454  {
455  should_abort = true;
456  ROS_WARN("Aborting goal because we haven't heard from the controller in %.3lf seconds",
457  (now - last_controller_state_->header.stamp).toSec());
458  }
459 
460  if (should_abort)
461  {
462  // Stops the controller.
463  trajectory_msgs::JointTrajectory empty;
464  empty.joint_names = joint_names_;
465  pub_controller_command_.publish(empty);
466 
467  // Marks the current goal as aborted.
468  active_goal_.setAborted();
469  has_active_goal_ = false;
470  }
471  }
472  }
473 
474 
475  void cancelCB(GoalHandle gh)
476  {
477  if (active_goal_ == gh)
478  {
479  // Stops the controller.
480  trajectory_msgs::JointTrajectory empty;
481  empty.joint_names = joint_names_;
482  pub_controller_command_.publish(empty);
483 
484  // Marks the current goal as canceled.
485  active_goal_.setCanceled();
486  has_active_goal_ = false;
487  }
488  }
489 
490  pr2_controllers_msgs::JointTrajectoryControllerStateConstPtr last_controller_state_;
491  void controllerStateCB(const pr2_controllers_msgs::JointTrajectoryControllerStateConstPtr &msg)
492  {
493  last_controller_state_ = msg;
494  ros::Time now = ros::Time::now();
495 
496  if (!has_active_goal_)
497  return;
498 
500  try
501  {
502  KDL::JntArray jnt_pos(msg->joint_names.size());
503  for(unsigned int i = 0; i < msg->joint_names.size(); i++)
504  jnt_pos(i) = msg->actual.positions[i];
505 
506  KDL::Frame pose;
507  pose_solver_->JntToCart(jnt_pos, pose);
508 
509  tf::Transform frame_in_root;
510  tf::poseKDLToTF(pose, frame_in_root);
511 
512  tf::Vector3 axis_in_frame = pointing_axis_.normalized();
513  tf::Vector3 target_from_frame = target_in_root_ - frame_in_root.getOrigin();
514 
515  target_from_frame.normalize();
516  tf::Vector3 current_in_frame = frame_in_root.getBasis().inverse()*target_from_frame;
517 
518  pr2_controllers_msgs::PointHeadFeedback feedback;
519  feedback.pointing_angle_error = current_in_frame.angle(axis_in_frame);
520  active_goal_.publishFeedback(feedback);
521 
522  if (feedback.pointing_angle_error < success_angle_threshold_)
523  {
524  active_goal_.setSucceeded();
525  has_active_goal_ = false;
526  }
527  }
528  catch(const tf::TransformException &ex)
529  {
530  ROS_ERROR("Could not transform: %s", ex.what());
531  }
532  }
533 
534 
535 };
536 
537 int main(int argc, char** argv)
538 {
539  ros::init(argc, argv, "point_head_action");
540  ros::NodeHandle node;
541  ControlHead ch(node);
542  ros::spin();
543  return 0;
544 }
ros::NodeHandle pnh_
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
std::vector< std::string > joint_names_
std::string action_name_
std::string root_
std::string default_pointing_frame_
static void pointMsgToTF(const geometry_msgs::Point &msg_v, Point &bt_v)
void publish(const boost::shared_ptr< M > &message) const
bool initString(const std::string &xmlstring)
ServerGoalHandle< pr2_controllers_msgs::PointHeadAction > GoalHandle
std::string pointing_frame_
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
tf::Stamped< tf::Point > target_in_pan_
bool getParent(const std::string &frame_id, ros::Time time, std::string &parent) const
TFSIMD_FORCE_INLINE Matrix3x3 & getBasis()
urdf::Model urdf_model_
bool sleep() const
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
bool call(MReq &req, MRes &res)
std::string getName(void *handle)
bool found
double success_angle_threshold_
void transformPoint(const std::string &target_frame, const geometry_msgs::PointStamped &stamped_in, geometry_msgs::PointStamped &stamped_out) const
tf::Vector3 pointing_axis_
Matrix3x3 inverse() const
#define M_PI
TFSIMD_FORCE_INLINE tfScalar angle(const Vector3 &v) const
pr2_controllers_msgs::JointTrajectoryControllerStateConstPtr last_controller_state_
#define ROS_WARN(...)
TFSIMD_FORCE_INLINE Vector3 cross(const Vector3 &v) const
void controllerStateCB(const pr2_controllers_msgs::JointTrajectoryControllerStateConstPtr &msg)
ROSCPP_DECL void spin(Spinner &spinner)
ros::Subscriber command_sub_
bool waitForTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration &timeout, const ros::Duration &polling_sleep_duration=ros::Duration(0.01), std::string *error_msg=NULL) const
ros::Publisher pub_controller_command_
boost::scoped_ptr< KDL::ChainJntToJacSolver > jac_solver_
TFSIMD_FORCE_INLINE const tfScalar & x() const
TFSIMD_FORCE_INLINE Vector3 normalized() const
actionlib::ActionServer< pr2_controllers_msgs::PointHeadAction > PHAS
ros::NodeHandle nh_
static void vector3MsgToTF(const geometry_msgs::Vector3 &msg_v, Vector3 &bt_v)
TFSIMD_FORCE_INLINE const tfScalar & z() const
void poseKDLToTF(const KDL::Frame &k, tf::Pose &t)
void transformTFToKDL(const tf::Transform &t, KDL::Frame &k)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
std::string pan_parent_
TFSIMD_FORCE_INLINE Vector3 normalized() const
ROSCPP_DECL bool ok()
TFSIMD_FORCE_INLINE const tfScalar & y() const
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
ControlHead(const ros::NodeHandle &node)
void goalCB(GoalHandle gh)
void watchdog(const ros::TimerEvent &e)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
unsigned int getNrOfJoints() const
bool treeFromString(const std::string &xml, KDL::Tree &tree)
int main(int argc, char **argv)
std::string tip_
TFSIMD_FORCE_INLINE Vector3 & getOrigin()
tf::Point target_in_root_
TFSIMD_FORCE_INLINE Vector3 & normalize()
GoalHandle active_goal_
tf::TransformListener tfl_
bool getChain(const std::string &chain_root, const std::string &chain_tip, Chain &chain) const
geometry_msgs::PointStamped target_
unsigned int getNrOfSegments() const
trajectory_msgs::JointTrajectory traj
void cancelCB(GoalHandle gh)
std::string pan_link_
static Time now()
ros::Subscriber sub_controller_state_
ros::Timer watchdog_timer_
PHAS::GoalHandle GoalHandle
void printVector3(const char *label, tf::Vector3 v)
unsigned int getNrOfJoints() const
#define ROS_ERROR(...)
std::string node_name_
ros::ServiceClient cli_query_traj_
boost::scoped_ptr< KDL::ChainFkSolverPos > pose_solver_
int ALVAR_EXPORT diff(const std::vector< C > &v, std::vector< C > &ret)
TFSIMD_FORCE_INLINE tfScalar length() const
#define ROS_DEBUG(...)


robotican_common
Author(s):
autogenerated on Wed Jan 3 2018 03:48:33