industrial_robot_client/joint_trajectory_streamer.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 
33 #include <map>
34 #include <vector>
35 #include <string>
36 
39 
41 {
42 namespace joint_trajectory_streamer
43 {
44 
45 bool JointTrajectoryStreamer::init(SmplMsgConnection* connection, const std::map<int, RobotGroup> &robot_groups,
46  const std::map<std::string, double> &velocity_limits)
47 {
48  bool rtn = true;
49 
50  ROS_INFO("JointTrajectoryStreamer: init");
51 
52  rtn &= JointTrajectoryInterface::init(connection, robot_groups, velocity_limits);
53 
54  this->mutex_.lock();
55  this->current_point_ = 0;
57  this->streaming_thread_ =
58  new boost::thread(boost::bind(&JointTrajectoryStreamer::streamingThread, this));
59  ROS_INFO("Unlocking mutex");
60  this->mutex_.unlock();
61 
62  return rtn;
63 }
64 
65 bool JointTrajectoryStreamer::init(SmplMsgConnection* connection, const std::vector<std::string> &joint_names,
66  const std::map<std::string, double> &velocity_limits)
67 {
68  bool rtn = true;
69 
70  ROS_INFO("JointTrajectoryStreamer: init");
71 
72  rtn &= JointTrajectoryInterface::init(connection, joint_names, velocity_limits);
73 
74  this->mutex_.lock();
75  this->current_point_ = 0;
77  this->streaming_thread_ =
78  new boost::thread(boost::bind(&JointTrajectoryStreamer::streamingThread, this));
79  ROS_INFO("Unlocking mutex");
80  this->mutex_.unlock();
81 
82  return rtn;
83 }
84 
86 {
87  delete this->streaming_thread_;
88 }
89 
90 void JointTrajectoryStreamer::jointTrajectoryCB(const motoman_msgs::DynamicJointTrajectoryConstPtr &msg)
91 {
92  ROS_INFO("Receiving joint trajectory message");
93 
94  // read current state value (should be atomic)
95  int state = this->state_;
96 
97  ROS_DEBUG("Current state is: %d", state);
98  if (TransferStates::IDLE != state)
99  {
100  if (msg->points.empty())
101  ROS_INFO("Empty trajectory received, canceling current trajectory");
102  else
103  ROS_ERROR("Trajectory splicing not yet implemented, stopping current motion.");
104 
105  this->mutex_.lock();
106  trajectoryStop();
107  this->mutex_.unlock();
108  return;
109  }
110 
111  if (msg->points.empty())
112  {
113  ROS_INFO("Empty trajectory received while in IDLE state, nothing is done");
114  return;
115  }
116 
117  // calc new trajectory
118  std::vector<SimpleMessage> new_traj_msgs;
119  if (!trajectory_to_msgs(msg, &new_traj_msgs))
120  return;
121 
122  // send command messages to robot
123  send_to_robot(new_traj_msgs);
124 }
125 
126 void JointTrajectoryStreamer::jointTrajectoryCB(const trajectory_msgs::JointTrajectoryConstPtr &msg)
127 {
128  ROS_INFO("Receiving joint trajectory message");
129 
130  // read current state value (should be atomic)
131  int state = this->state_;
132 
133  ROS_DEBUG("Current state is: %d", state);
134  if (TransferStates::IDLE != state)
135  {
136  if (msg->points.empty())
137  ROS_INFO("Empty trajectory received, canceling current trajectory");
138  else
139  ROS_ERROR("Trajectory splicing not yet implemented, stopping current motion.");
140 
141  this->mutex_.lock();
142  trajectoryStop();
143  this->mutex_.unlock();
144  return;
145  }
146 
147  if (msg->points.empty())
148  {
149  ROS_INFO("Empty trajectory received while in IDLE state, nothing is done");
150  return;
151  }
152 
153  // calc new trajectory
154  std::vector<SimpleMessage> new_traj_msgs;
155  if (!trajectory_to_msgs(msg, &new_traj_msgs))
156  return;
157 
158  // send command messages to robot
159  send_to_robot(new_traj_msgs);
160 }
161 
162 bool JointTrajectoryStreamer::send_to_robot(const std::vector<SimpleMessage>& messages)
163 {
164  ROS_INFO("Loading trajectory, setting state to streaming");
165  this->mutex_.lock();
166  {
167  ROS_INFO("Executing trajectory of size: %d", static_cast<int>(messages.size()));
168  this->current_traj_ = messages;
169  this->current_point_ = 0;
172  }
173  this->mutex_.unlock();
174 
175  return true;
176 }
177 
178 bool JointTrajectoryStreamer::trajectory_to_msgs(const trajectory_msgs::JointTrajectoryConstPtr& traj,
179  std::vector<SimpleMessage>* msgs)
180 {
181  // use base function to transform points
183  return false;
184 
185  // pad trajectory as required for minimum streaming buffer size
186  if (!msgs->empty() && (msgs->size() < (size_t)min_buffer_size_))
187  {
188  ROS_DEBUG("Padding trajectory: current(%d) => minimum(%d)", static_cast<int>(msgs->size()), min_buffer_size_);
189  while (msgs->size() < (size_t)min_buffer_size_)
190  msgs->push_back(msgs->back());
191  }
192 
193  return true;
194 }
195 
196 bool JointTrajectoryStreamer::trajectory_to_msgs(const motoman_msgs::DynamicJointTrajectoryConstPtr& traj,
197  std::vector<SimpleMessage>* msgs)
198 {
199  // use base function to transform points
201  return false;
202 
203  // pad trajectory as required for minimum streaming buffer size
204  if (!msgs->empty() && (msgs->size() < (size_t)min_buffer_size_))
205  {
206  ROS_DEBUG("Padding trajectory: current(%d) => minimum(%d)", static_cast<int>(msgs->size()), min_buffer_size_);
207  while (msgs->size() < (size_t)min_buffer_size_)
208  msgs->push_back(msgs->back());
209  }
210 
211  return true;
212 }
213 
214 
216 {
217  int connectRetryCount = 1;
218 
219  ROS_INFO("Starting joint trajectory streamer thread");
220  while (ros::ok())
221  {
222  ros::Duration(0.005).sleep();
223 
224  // automatically re-establish connection, if required
225  if (connectRetryCount-- > 0)
226  {
227  ROS_INFO("Connecting to robot motion server");
228  this->connection_->makeConnect();
229  ros::Duration(0.250).sleep(); // wait for connection
230 
231  if (this->connection_->isConnected())
232  connectRetryCount = 0;
233  else if (connectRetryCount <= 0)
234  {
235  ROS_ERROR("Timeout connecting to robot controller. Send new motion command to retry.");
237  }
238  continue;
239  }
240 
241  this->mutex_.lock();
242 
243  SimpleMessage msg, tmpMsg, reply;
244 
245  switch (this->state_)
246  {
248  ros::Duration(0.250).sleep(); // slower loop while waiting for new trajectory
249  break;
250 
252  if (this->current_point_ >= static_cast<int>(this->current_traj_.size()))
253  {
254  ROS_INFO("Trajectory streaming complete, setting state to IDLE");
256  break;
257  }
258 
259  if (!this->connection_->isConnected())
260  {
261  ROS_DEBUG("Robot disconnected. Attempting reconnect...");
262  connectRetryCount = 5;
263  break;
264  }
265 
266  tmpMsg = this->current_traj_[this->current_point_];
267  msg.init(tmpMsg.getMessageType(), CommTypes::SERVICE_REQUEST,
268  ReplyTypes::INVALID, tmpMsg.getData()); // set commType=REQUEST
269 
270  ROS_DEBUG("Sending joint trajectory point");
271  if (this->connection_->sendAndReceiveMsg(msg, reply, false))
272  {
273  ROS_INFO("Point[%d of %d] sent to controller",
274  this->current_point_, static_cast<int>(this->current_traj_.size()));
275  this->current_point_++;
276  }
277  else
278  ROS_WARN("Failed sent joint point, will try again");
279 
280  break;
281  default:
282  ROS_ERROR("Joint trajectory streamer: unknown state");
284  break;
285  }
286 
287  this->mutex_.unlock();
288  }
289 
290  ROS_WARN("Exiting trajectory streamer thread");
291 }
292 
294 {
296 
297  ROS_DEBUG("Stop command sent, entering idle mode");
299 }
300 
301 } // namespace joint_trajectory_streamer
302 } // namespace industrial_robot_client
303 
bool sleep() const
#define ROS_WARN(...)
bool sendAndReceiveMsg(industrial::simple_message::SimpleMessage &send, industrial::simple_message::SimpleMessage &recv, bool verbose=false)
bool send_to_robot(const std::vector< JointTrajPtMessage > &messages)
#define ROS_INFO(...)
virtual bool init(std::string default_ip="", int default_port=StandardSocketPorts::MOTION)
ROSCPP_DECL bool ok()
virtual bool init(SmplMsgConnection *connection, const std::vector< std::string > &joint_names, const std::map< std::string, double > &velocity_limits=std::map< std::string, double >())
static Time now()
#define ROS_ERROR(...)
virtual bool trajectory_to_msgs(const trajectory_msgs::JointTrajectoryConstPtr &traj, std::vector< JointTrajPtMessage > *msgs)
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