joint_trajectory_generator.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2009, 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 Willow Garage, Inc. 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  * Author: Eitan Marder-Eppstein
36  *********************************************************************/
37 #include <ros/ros.h>
40 
41 #include <pr2_controllers_msgs/JointTrajectoryAction.h>
42 #include <pr2_controllers_msgs/JointTrajectoryControllerState.h>
43 
44 #include <angles/angles.h>
45 #include <urdf/model.h>
46 #include <urdf_model/joint.h>
47 
49 
52  {
53  private:
56  public:
57  JointTrajectoryGenerator(std::string name) :
58  as_(ros::NodeHandle(), "joint_trajectory_generator",
59  boost::bind(&JointTrajectoryGenerator::executeCb, this, _1),
60  false),
61  ac_("joint_trajectory_action"),
62  got_state_(false)
63  {
66 
67  ros::NodeHandle pn("~");
68  pn.param("max_acc", max_acc_, 0.5);
69  pn.param("max_vel", max_vel_, 5.0);
70 
71  // Load Robot Model
72  ROS_DEBUG("Loading robot model");
73  std::string xml_string;
74  ros::NodeHandle nh_toplevel;
75  if (!nh_toplevel.getParam(std::string("/robot_description"), xml_string))
76  throw ros::Exception("Could not find paramter robot_description on parameter server");
77 
78  if(!robot_model_.initString(xml_string))
79  throw ros::Exception("Could not parse robot model");
80 
81  ros::Rate r(10.0);
82  while(!got_state_){
83  ros::spinOnce();
84  r.sleep();
85  }
86 
88  as_.start();
89  ROS_INFO("%s: Initialized",name.c_str());
90  }
91 
92  void jointStateCb(const pr2_controllers_msgs::JointTrajectoryControllerStateConstPtr& state){
93  boost::mutex::scoped_lock lock(mutex_);
94  for(unsigned int i = 0; i < state->joint_names.size(); ++i){
95  current_state_[state->joint_names[i]] = state->actual.positions[i];
96  }
97  got_state_ = true;
98  }
99 
100  pr2_controllers_msgs::JointTrajectoryGoal createGoal(const pr2_controllers_msgs::JointTrajectoryGoal& goal){
101  pr2_controllers_msgs::JointTrajectoryGoal new_goal;
102  new_goal.trajectory.header = goal.trajectory.header;
103  new_goal.trajectory.joint_names = goal.trajectory.joint_names;
104 
105  size_t n_traj_points = goal.trajectory.points.size(),
106  n_joint_names = goal.trajectory.joint_names.size();
107 
108  // Increase traj length to account for the initial pose
109  ROS_DEBUG_STREAM("Initial trajectory has "<<n_traj_points<<" points.");
110  new_goal.trajectory.points.resize(n_traj_points + 1);
111 
112  // Set joint names
113  for(size_t i=0; i<n_traj_points+1; i++) {
114  new_goal.trajectory.points[i].positions.resize(n_joint_names);
115  }
116 
117  {
118  boost::mutex::scoped_lock lock(mutex_);
119  //add the current point as the start of the trajectory
120  for(unsigned int i = 0; i < n_joint_names; ++i){
121  // Generate the first point
122  if(current_state_.find(new_goal.trajectory.joint_names[i]) == current_state_.end()) {
123  ROS_FATAL_STREAM("Joint names in goal and controller don't match. Something is very wrong. Goal joint name: "<<new_goal.trajectory.joint_names[i]);
124  throw std::runtime_error("Joint names in goal and controller don't match. Something is very wrong.");
125  }
126  new_goal.trajectory.points[0].positions[i] = current_state_[new_goal.trajectory.joint_names[i]];
127 
128  // Get the joint and calculate the offset from the current state
129 #if URDFDOM_1_0_0_API
130  urdf::JointConstSharedPtr joint = robot_model_.getJoint(new_goal.trajectory.joint_names[i]);
131 #else
132  boost::shared_ptr<const urdf::Joint> joint = robot_model_.getJoint(new_goal.trajectory.joint_names[i]);
133 #endif
134  double offset = 0;
135 
136  double goal_position = goal.trajectory.points[0].positions[i],
137  current_position = new_goal.trajectory.points[0].positions[i];
138 
139  if(joint->type == urdf::Joint::REVOLUTE) {
140  offset = 0;
141  } else if(joint->type == urdf::Joint::CONTINUOUS) {
142  offset = current_position - goal_position - angles::shortest_angular_distance(goal_position, current_position);
143  } else {
144  ROS_WARN("Unknown joint type in joint trajectory. This joint might not be unwrapped properly. Supported joint types are urdf::Joint::REVOLUTE and urdf::Joint::CONTINUOUS");
145  offset = 0;
146  }
147 
148  // Apply offset to each point in the trajectory on this joint
149  for(unsigned int j=0; j < n_traj_points; j++) {
150  new_goal.trajectory.points[j+1].time_from_start = goal.trajectory.points[j].time_from_start;
151  new_goal.trajectory.points[j+1].positions[i] = goal.trajectory.points[j].positions[i] + offset;
152  }
153  }
154  }
155 
156  //todo pass into trajectory generator here
157  trajectory::TrajectoryGenerator g(max_vel_, max_acc_, new_goal.trajectory.joint_names.size());
158 
159  //do the trajectory generation
160  g.generate(new_goal.trajectory, new_goal.trajectory);
161 
162  return new_goal;
163  }
164 
165  void executeCb(const pr2_controllers_msgs::JointTrajectoryGoalConstPtr& goal){
166  ROS_DEBUG("Got a goal");
167 
168  pr2_controllers_msgs::JointTrajectoryGoal full_goal;
169  try {
170  full_goal = createGoal(*goal);
171  } catch (ros::Exception ex) {
172  ROS_ERROR_STREAM(ex.what());
173  as_.setAborted();
174  return;
175  }
176 
178 
179  while(ros::ok() && !ac_.waitForResult(ros::Duration(0.05))){
180  if(as_.isPreemptRequested()){
181  if(as_.isNewGoalAvailable()){
182  ROS_DEBUG("Preempted by new goal");
184  full_goal = createGoal(*new_goal);
187  boost::bind(&JointTrajectoryGenerator::feedbackCb, this, _1));
188  }
189  else{
190  ROS_DEBUG("Preempted by cancel");
191  ac_.cancelGoal();
192  }
193  }
194  }
195 
196  if(!ros::ok()){
197  as_.setAborted();
198  return;
199  }
200 
202  pr2_controllers_msgs::JointTrajectoryResultConstPtr result = ac_.getResult();
203 
205  ROS_DEBUG("Preempted");
206  as_.setPreempted(*result);
207  }
209  ROS_DEBUG("Succeeded ");
210  as_.setSucceeded(*result);
211  }
213  ROS_DEBUG("Aborted ");
214  as_.setAborted(*result);
215  }
216  else
217  as_.setAborted(*result, "Unknown result from joint_trajectory_action");
218 
219  }
220 
221  void feedbackCb(const pr2_controllers_msgs::JointTrajectoryFeedbackConstPtr& feedback){
222  as_.publishFeedback(feedback);
223  }
224 
225  private:
226  JTAS as_;
227  JTAC ac_;
228  boost::mutex mutex_;
229  std::map<std::string, double> current_state_;
234 
235  };
236 };
237 
238 int main(int argc, char** argv){
239  ros::init(argc, argv, "joint_trajectory_generator_node");
241 
242  ros::spin();
243 
244  return 0;
245 }
boost::shared_ptr< const Goal > acceptNewGoal()
void publishFeedback(const FeedbackConstPtr &feedback)
bool waitForServer(const ros::Duration &timeout=ros::Duration(0, 0)) const
URDF_EXPORT bool initString(const std::string &xmlstring)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
pr2_controllers_msgs::JointTrajectoryGoal createGoal(const pr2_controllers_msgs::JointTrajectoryGoal &goal)
bool waitForResult(const ros::Duration &timeout=ros::Duration(0, 0))
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
ROSCPP_DECL const std::string & getName()
#define ROS_WARN(...)
void setSucceeded(const Result &result=Result(), const std::string &text=std::string(""))
void setPreempted(const Result &result=Result(), const std::string &text=std::string(""))
actionlib::SimpleActionClient< pr2_controllers_msgs::JointTrajectoryAction > JTAC
#define ROS_FATAL_STREAM(args)
actionlib::SimpleActionServer< pr2_controllers_msgs::JointTrajectoryAction > JTAS
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
ROSCPP_DECL bool ok()
void executeCb(const pr2_controllers_msgs::JointTrajectoryGoalConstPtr &goal)
ROSCPP_DECL void spin()
int main(int argc, char **argv)
#define ROS_DEBUG_STREAM(args)
void generate(const trajectory_msgs::JointTrajectory &traj_in, trajectory_msgs::JointTrajectory &traj_out)
bool sleep()
boost::function< void(const SimpleClientGoalState &state, const ResultConstPtr &result)> SimpleDoneCallback
void setAborted(const Result &result=Result(), const std::string &text=std::string(""))
void sendGoal(const Goal &goal, SimpleDoneCallback done_cb=SimpleDoneCallback(), SimpleActiveCallback active_cb=SimpleActiveCallback(), SimpleFeedbackCallback feedback_cb=SimpleFeedbackCallback())
void jointStateCb(const pr2_controllers_msgs::JointTrajectoryControllerStateConstPtr &state)
bool getParam(const std::string &key, std::string &s) const
void feedbackCb(const pr2_controllers_msgs::JointTrajectoryFeedbackConstPtr &feedback)
SimpleClientGoalState getState() const
#define ROS_ERROR_STREAM(args)
ResultConstPtr getResult() const
ROSCPP_DECL void spinOnce()
def shortest_angular_distance(from_angle, to_angle)
#define ROS_DEBUG(...)


joint_trajectory_generator
Author(s): Eitan Marder-Eppstein, Wim Meeusen
autogenerated on Fri Jun 7 2019 22:06:38