fsrobo_r_joint_trajectory_streamer.cpp
Go to the documentation of this file.
1 /*********************************************************************
2 * FSRobo-R Package BSDL
3 * ---------
4 * Copyright (C) 2019 FUJISOFT. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without modification,
7 * are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation and/or
12 * other materials provided with the distribution.
13 * 3. Neither the name of the copyright holder nor the names of its contributors
14 * may be used to endorse or promote products derived from this software without
15 * specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *********************************************************************/
28 
30 #include <sstream>
31 
32 namespace fsrobo_r_driver
33 {
34 namespace joint_trajectory_streamer
35 {
36 bool FSRoboRJointTrajectoryStreamer::init(SmplMsgConnection *connection, const std::vector<std::string> &joint_names,
37  const std::map<std::string, double> &velocity_limits)
38 {
39  bool rtn = true;
40 
41  ROS_INFO("FSRoboRJointTrajectoryStreamer: init");
42 
43  rtn &= JointTrajectoryInterface::init(connection, joint_names, velocity_limits);
44 
45  this->mutex_.lock();
46  this->current_point_ = 0;
48  this->streaming_thread_ =
49  new boost::thread(boost::bind(&FSRoboRJointTrajectoryStreamer::streamingThread, this));
50  ROS_INFO("Unlocking mutex");
51  this->mutex_.unlock();
52 
53  robot_program_executor_.init(connection);
55 
56  return rtn;
57 }
59 {
60  delete this->streaming_thread_;
61 }
62 
63 void FSRoboRJointTrajectoryStreamer::jointTrajectoryCB(const trajectory_msgs::JointTrajectoryConstPtr &msg)
64 {
65  ROS_INFO("Receiving joint trajectory message");
66 
67  // read current state value (should be atomic)
68  int state = this->state_;
69 
70  ROS_DEBUG("Current state is: %d", state);
71  if (TransferStates::IDLE != state)
72  {
73  if (msg->points.empty())
74  ROS_INFO("Empty trajectory received, canceling current trajectory");
75  else
76  ROS_ERROR("Trajectory splicing not yet implemented, stopping current motion.");
77 
78  this->mutex_.lock();
80  this->mutex_.unlock();
81  return;
82  }
83 
84  if (msg->points.empty())
85  {
86  ROS_INFO("Empty trajectory received while in IDLE state, send abort command anyway.");
87  this->mutex_.lock();
89  this->mutex_.unlock();
90  return;
91  }
92 
93  // calc new trajectory
94  std::vector<JointTrajPtMessage> new_traj_msgs;
95  if (!trajectory_to_msgs(msg, &new_traj_msgs))
96  return;
97 
98  // calculate average velocity between waypoints
99  int pos = 0;
100  const float coefficient = 0.5;
101  for(auto itr = new_traj_msgs.begin(); itr != new_traj_msgs.end(); ++itr){
102  if(pos != 0){
103  float vel = itr->point_.getVelocity();
104  float prev_vel = (itr - 1)->point_.getVelocity();
105  ROS_DEBUG("prev_vel[%d] => %f, vel[%d] => %f", pos, prev_vel, pos, vel);
106  float new_vel = prev_vel + coefficient*(vel - prev_vel);
107  ROS_DEBUG("new_vel[%d] => %f", pos, new_vel);
108  itr->point_.setVelocity(new_vel);
109  }
110  pos++;
111  }
112 
113  // send command messages to robot
114  send_to_robot(new_traj_msgs);
115 }
116 
117 bool FSRoboRJointTrajectoryStreamer::send_to_robot(const std::vector<JointTrajPtMessage> &messages)
118 {
119  ROS_INFO("Loading trajectory, setting state to streaming");
120  this->mutex_.lock();
121  {
122  ROS_INFO("Executing trajectory of size: %d", (int)messages.size());
123  this->current_traj_ = messages;
124  this->current_point_ = 0;
127  }
128  this->mutex_.unlock();
129 
130  return true;
131 }
132 
133 bool FSRoboRJointTrajectoryStreamer::trajectory_to_msgs(const trajectory_msgs::JointTrajectoryConstPtr &traj, std::vector<JointTrajPtMessage> *msgs)
134 {
135  // use base function to transform points
137  return false;
138 
139  // pad trajectory as required for minimum streaming buffer size
140  if (!msgs->empty() && (msgs->size() < (size_t)min_buffer_size_))
141  {
142  ROS_DEBUG("Padding trajectory: current(%d) => minimum(%d)", (int)msgs->size(), min_buffer_size_);
143  while (msgs->size() < (size_t)min_buffer_size_)
144  msgs->push_back(msgs->back());
145  }
146 
147  return true;
148 }
149 
151 {
152  JointTrajPtMessage jtpMsg;
153  int connectRetryCount = 1;
154 
155  ROS_INFO("Starting joint trajectory streamer thread");
156  while (ros::ok())
157  {
158  ros::Duration(0.001).sleep();
159 
160  // automatically re-establish connection, if required
161  if (connectRetryCount-- > 0)
162  {
163  ROS_INFO("Connecting to robot motion server");
164  this->connection_->makeConnect();
165  ros::Duration(0.250).sleep(); // wait for connection
166 
167  if (this->connection_->isConnected())
168  connectRetryCount = 0;
169  else if (connectRetryCount <= 0)
170  {
171  ROS_ERROR("Timeout connecting to robot controller. Send new motion command to retry.");
173  }
174  continue;
175  }
176 
177  this->mutex_.lock();
178 
179  SimpleMessage msg, reply;
180 
181  switch (this->state_)
182  {
184  //ros::Duration(0.250).sleep(); // slower loop while waiting for new trajectory
185  break;
186 
188  if (this->current_point_ >= (int)this->current_traj_.size())
189  {
190  ROS_INFO("Trajectory streaming complete, setting state to IDLE");
192  break;
193  }
194 
195  if (this->current_point_ == 0 && (int)this->current_traj_.size() > 1)
196  {
197  ROS_INFO("First trajectory remove");
198  this->current_point_++;
199  break;
200  }
201 
202  if (!this->connection_->isConnected())
203  {
204  ROS_DEBUG("Robot disconnected. Attempting reconnect...");
205  connectRetryCount = 5;
206  break;
207  }
208 
209  jtpMsg = this->current_traj_[this->current_point_];
210  jtpMsg.toRequest(msg);
211 
212  ROS_DEBUG("Sending joint trajectory point");
213  if (this->connection_->sendAndReceiveMsg(msg, reply, false))
214  {
215  ROS_INFO("Point[%d of %d] sent to controller",
216  this->current_point_, (int)this->current_traj_.size());
217  this->current_point_++;
218  }
219  else
220  ROS_WARN("Failed sent joint point, will try again");
221 
222  break;
223  default:
224  ROS_ERROR("Joint trajectory streamer: unknown state");
226  break;
227  }
228 
229  this->mutex_.unlock();
230  }
231 
232  ROS_WARN("Exiting trajectory streamer thread");
233 }
234 
236 {
238 
239  ROS_DEBUG("Stop command sent, entering idle mode");
241 }
242 
243 
244 bool FSRoboRJointTrajectoryStreamer::executeRobotProgramCB(fsrobo_r_msgs::ExecuteRobotProgram::Request &req, fsrobo_r_msgs::ExecuteRobotProgram::Response &res)
245 {
246  ROS_WARN("ExecuteRobotProgram!");
247 
248  ROS_WARN("%s", req.name.c_str());
249  bool exec_result;
250 
251  this->mutex_.lock();
252  bool result = robot_program_executor_.execute(req.name, req.param, exec_result);
253  this->mutex_.unlock();
254 
255  res.result = exec_result;
256 
257  if (!result)
258  {
259  ROS_ERROR("Executing robot program %s failed", req.name.c_str());
260  return false;
261  }
262 
263  return true;
264 }
265 
266 
267 } // namespace joint_trajectory_streamer
268 } // namespace fsrobo_r_driver
bool executeRobotProgramCB(fsrobo_r_msgs::ExecuteRobotProgram::Request &req, fsrobo_r_msgs::ExecuteRobotProgram::Response &res)
bool sleep() const
virtual void jointTrajectoryCB(const trajectory_msgs::JointTrajectoryConstPtr &msg)
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
virtual bool trajectory_to_msgs(const trajectory_msgs::JointTrajectoryConstPtr &traj, std::vector< JointTrajPtMessage > *msgs)
#define ROS_WARN(...)
virtual bool toRequest(industrial::simple_message::SimpleMessage &msg)
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 >())
Class initializer.
#define ROS_INFO(...)
virtual bool init(std::string default_ip="", int default_port=StandardSocketPorts::MOTION)
ROSCPP_DECL bool ok()
bool execute(std::string name, std::string param, bool &result)
Execute robot program on the controller.
static Time now()
#define ROS_ERROR(...)
virtual bool trajectory_to_msgs(const trajectory_msgs::JointTrajectoryConstPtr &traj, std::vector< JointTrajPtMessage > *msgs)
#define ROS_DEBUG(...)


fsrobo_r_driver
Author(s): F-ROSROBO
autogenerated on Sun Feb 9 2020 03:58:29