play_motion_builder.cpp
Go to the documentation of this file.
1 #include "play_motion_builder.h"
2 
3 #include <sensor_msgs/JointState.h>
4 #include <fstream>
5 
6 namespace
7 {
8 std::string exec(const char *cmd)
9 {
10  std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
11  if (!pipe)
12  return "Error";
13  char buffer[1024];
14  std::string result = "";
15  while (!feof(pipe.get()))
16  {
17  if (fgets(buffer, 128, pipe.get()) != NULL)
18  result += buffer;
19  }
20  return result;
21 }
22 } // namespace
23 
24 namespace pal
25 {
27  : private_nh_("~")
28  , action_server_(private_nh_, "build", false)
29  , run_motion_server_(private_nh_, "run",
30  boost::bind(&ROSMotionBuilderNode::executeRunMotionCb, this, _1), false)
31  , play_motion_client_("/play_motion")
32  , running_(false)
33 {
34  // Register callbacks
37  boost::bind(&ROSMotionBuilderNode::buildMotionPreemptCb, this));
39  boost::bind(&ROSMotionBuilderNode::runMotionPreemptCb, this));
40 }
41 
43 {
44  // Get Robot descriptions
45  std::string robot_desc_param =
46  private_nh_.param("robot_description_param", std::string("/robot_description"));
47  if (!nh_.getParam(robot_desc_param, robot_description_))
48  {
49  ROS_ERROR("Couldn't find robot description for this robot");
50  return false;
51  }
52  std::string semantic_desc_param =
53  private_nh_.param("semantic_description", std::string("/robot_description_semantic"));
54  if (!nh_.getParam(semantic_desc_param, semantic_description_))
55  {
56  ROS_ERROR("Couldn't find semantic description for this robot");
57  return false;
58  }
59 
60  // Get extra joints
61  std::string extra_joints_param_name = private_nh_.param(
62  "extra_joints_param_name",
63  std::string("/play_motion/approach_planner/exclude_from_planning_joints"));
64  XmlRpc::XmlRpcValue extra_joints_param;
65  if (nh_.getParam(extra_joints_param_name, extra_joints_param))
66  {
67  for (int i = 0; i < extra_joints_param.size(); ++i)
68  {
69  extra_joints_.push_back(static_cast<std::string>(extra_joints_param[i]));
70  }
71  }
72 
73  // Set up Services
81  "list_joint_groups", &ROSMotionBuilderNode::listJointGroupsCb, this);
82 
83  // Start the action server
86 
87  return true;
88 }
89 
91 {
92  play_motion_builder_msgs::BuildMotionGoalConstPtr goal = action_server_.acceptNewGoal();
93  if (goal->motion != "")
94  {
95  // Load an existing motion
96  XmlRpc::XmlRpcValue motion_cfg;
97  if (nh_.getParam("/play_motion/motions/" + goal->motion, motion_cfg))
98  {
99  // Process and load motion
101  extra_joints_));
102  ROS_INFO_STREAM("Motion " << goal->motion << " loaded");
103  ROS_DEBUG_STREAM("Using joint group: " << motion_->getCurrentGroup());
104  }
105  else
106  {
107  play_motion_builder_msgs::BuildMotionResult result;
108  result.ok = false;
109  result.message = "Couldn't find motion " + goal->motion;
110  action_server_.setAborted(result);
111  }
112  }
113  else
114  {
115  // Create a new empty motion
117  ROS_INFO("New motion ready");
118  }
119 
120  // Ready to process commands
121  running_ = true;
122  ROS_INFO("Motion Builder Ready");
123 }
124 
126 {
127  // Prevent any further actions on the motion
128  running_ = false;
129 
130  // Preempt the action
131  play_motion_builder_msgs::BuildMotionResult result;
132  result.ok = false;
133  result.message = "Process was preempted";
135 
136  // Clear the temporal motion created if necessary
137  if (motion_->getParamName() != "")
138  nh_.deleteParam("/play_motion/motions/" + motion_->getParamName());
139 
140  // Clear the motion
141  motion_.reset();
142 }
143 
145 {
147 }
148 
149 bool ROSMotionBuilderNode::editMotionCb(play_motion_builder_msgs::EditMotion::Request &req,
150  play_motion_builder_msgs::EditMotion::Response &res)
151 {
152  if (running_)
153  {
154  switch (req.action)
155  {
156  case play_motion_builder_msgs::EditMotion::Request::LIST:
157  // Don't modify the motion
158  break;
159  case play_motion_builder_msgs::EditMotion::Request::APPEND:
160  case play_motion_builder_msgs::EditMotion::Request::EDIT:
161  {
162  sensor_msgs::JointStateConstPtr joint_state =
163  ros::topic::waitForMessage<sensor_msgs::JointState>("/joint_states");
164  if (req.action == play_motion_builder_msgs::EditMotion::Request::APPEND)
165  {
166  // Append keyframe at the end
167  motion_->addKeyFrame(joint_state);
168  }
169  else
170  {
171  // Update requested frame id with current position
172  motion_->updateKeyFrame(joint_state, req.step_id);
173  }
174  }
175  break;
176  case play_motion_builder_msgs::EditMotion::Request::COPY_AS_LAST:
177  case play_motion_builder_msgs::EditMotion::Request::COPY_AS_NEXT:
178  motion_->copyFrame(req.step_id,
179  req.action == play_motion_builder_msgs::EditMotion::Request::COPY_AS_LAST ?
180  -1 :
181  req.step_id + 1);
182  break;
183  case play_motion_builder_msgs::EditMotion::Request::REMOVE:
184  motion_->removeKeyFrame(req.step_id);
185  break;
186  case play_motion_builder_msgs::EditMotion::Request::EDIT_TIME:
187  motion_->changeTime(req.step_id, req.time);
188  break;
189  default:
190  ROS_ERROR_STREAM("Unknown action code: " << req.action);
191  res.ok = false;
192  res.message = "Unknown action code";
193  }
194 
195  // Return current motion
196  motionToROSMsg(res.motion);
197  res.ok = true;
198  }
199  else
200  {
201  res.ok = false;
202  res.message = "No motion being built";
203  }
204 
205  return true;
206 }
207 
208 bool ROSMotionBuilderNode::storeMotionCb(play_motion_builder_msgs::StoreMotion::Request &req,
209  play_motion_builder_msgs::StoreMotion::Response &res)
210 {
211  if (running_)
212  {
213  /* clang-format off */
214  YAML::Emitter e;
215  e << YAML::BeginMap
216  << YAML::Key << "play_motion"
217  << YAML::Value << YAML::BeginMap
218  << YAML::Key << "motions"
219  << YAML::Value << YAML::BeginMap
220  << YAML::Key << req.ros_name
221  << YAML::Value << motion_->print(req.meta.name, req.meta.usage, req.meta.description)
222  << YAML::EndMap
223  << YAML::EndMap
224  << YAML::EndMap;
225  /* clang-format on */
226  ROS_INFO_STREAM("Motion: " << e.c_str());
227 
228  // Write file at output path
229  if (req.file_path != "")
230  {
231  try
232  {
233  std::ofstream file;
234  file.open(req.file_path);
235  file << e.c_str();
236  file.close();
237 
238  // Clean param
239  exec(("rosparam delete /play_motion/motions/" + req.ros_name).c_str());
240 
241  // Load to ros
242  exec(("rosparam load " + req.file_path).c_str());
243  ros::Duration d(1.0);
244  d.sleep();
245  }
246  catch (const std::ios_base::failure &err)
247  {
248  res.ok = false;
249  res.message = err.what();
250  return true;
251  }
252  }
253 
254  res.ok = true;
255  res.message = std::string(e.c_str());
256  }
257  else
258  {
259  res.ok = false;
260  res.message = "No motion being built, could not store.";
261  }
262 
263  return true;
264 }
265 
266 bool ROSMotionBuilderNode::changeJointsCb(play_motion_builder_msgs::ChangeJoints::Request &req,
267  play_motion_builder_msgs::ChangeJoints::Response &res)
268 {
269  if (running_)
270  {
271  res.ok = true;
272 
273  // Change used group
274  if (req.group != "")
275  {
276  if (!motion_->setCurrentGroup(req.group))
277  {
278  res.ok = false;
279  res.message = "Couldn't change group to " + req.group + ". ";
280  }
281  }
282  // Set joints to remove to Unused
283  if (req.joints_to_remove.size() > 0)
284  {
285  for (const auto &joint : req.joints_to_remove)
286  {
287  // Set joint to unused
288  if (!motion_->setExtraJointUsedState(joint, false))
289  {
290  res.ok = false;
291  res.message += "Couldn't remove extra joint " + joint + ". ";
292  }
293  }
294  }
295  // Set joints_to_add to Used
296  if (req.joints_to_add.size() > 0)
297  {
298  for (const auto &joint : req.joints_to_add)
299  {
300  // Set joint to used
301  if (!motion_->setExtraJointUsedState(joint, true))
302  {
303  res.ok = false;
304  res.message += "Couldn't add extra joint " + joint + ". ";
305  }
306  }
307  }
308 
309  // Reply
310  res.current_group = motion_->getCurrentGroup();
311  res.used_joints = motion_->getJoints();
312  }
313  else
314  {
315  res.ok = false;
316  res.message = "No motion being built";
317  }
318 
319  return true;
320 }
321 
322 bool ROSMotionBuilderNode::listJointGroupsCb(play_motion_builder_msgs::ListJointGroups::Request &,
323  play_motion_builder_msgs::ListJointGroups::Response &res)
324 {
325  if (running_)
326  {
327  res.groups = motion_->getJointGroups();
328  res.additional_joints = motion_->getExtraJoints();
329  res.available_joints = motion_->getAvailableJoints();
330  }
331 
332  return true;
333 }
334 
335 void ROSMotionBuilderNode::executeRunMotionCb(const play_motion_builder_msgs::RunMotionGoalConstPtr &goal)
336 {
337  if (!running_)
338  {
340  }
341  else
342  {
343  // Set up param name
344  if (motion_->getParamName() == "")
345  motion_->setParamName();
346 
347  if (goal->run_mode == play_motion_builder_msgs::RunMotionGoal::RUN_MOTION)
348  {
349  // Load motion to rosparam
350  motion_->loadYAML(goal->downshift == 0.0 ? 1.0 : goal->downshift);
351  }
352  else if (goal->run_mode == play_motion_builder_msgs::RunMotionGoal::GO_TO_STEP)
353  {
354  motion_->loadFrame(goal->step_id);
355  }
356  else
357  {
358  ROS_ERROR_STREAM("Unknown run mode: " << goal->run_mode);
360  }
361 
362  // Execute the motion
363  play_motion_msgs::PlayMotionGoal motion_goal;
364  motion_goal.motion_name = motion_->getParamName();
365  play_motion_client_.sendGoal(motion_goal);
366 
367  // Track goal
369  {
370  ros::Duration(0.1).sleep();
371  }
372 
373  // Motion finished with play motion state
377  run_motion_server_.setAborted(play_motion_builder_msgs::RunMotionResult(),
379  else
381  }
382 }
383 
384 void ROSMotionBuilderNode::motionToROSMsg(play_motion_builder_msgs::Motion &motion)
385 {
386  motion.joints = motion_->getJoints();
387  motion.used_group = motion_->getCurrentGroup();
388  for (unsigned int i = 0; i < motion_->size(); ++i)
389  {
390  play_motion_builder_msgs::Frame f;
391  for (const auto &joint : motion.joints)
392  {
393  f.pose.push_back(motion_->getKeyFrame(i).getJointPosition(joint));
394  }
395  f.time_from_last = motion_->getKeyFrame(i).getTime();
396 
397  motion.keyframes.push_back(f);
398  }
399 }
400 
401 } // namespace pal
d
boost::shared_ptr< const Goal > acceptNewGoal()
bool storeMotionCb(play_motion_builder_msgs::StoreMotion::Request &req, play_motion_builder_msgs::StoreMotion::Response &res)
f
bool deleteParam(const std::string &key) const
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
bool editMotionCb(play_motion_builder_msgs::EditMotion::Request &req, play_motion_builder_msgs::EditMotion::Response &res)
void setSucceeded(const Result &result=Result(), const std::string &text=std::string(""))
void motionToROSMsg(play_motion_builder_msgs::Motion &motion)
ros::ServiceServer list_joints_server_
bool param(const std::string &param_name, T &param_val, const T &default_val) const
void setPreempted(const Result &result=Result(), const std::string &text=std::string(""))
SimpleClientGoalState getState() const
#define ROS_INFO(...)
bool getParam(const std::string &key, std::string &s) const
std::vector< std::string > extra_joints_
void registerPreemptCallback(boost::function< void()> cb)
void executeRunMotionCb(const play_motion_builder_msgs::RunMotionGoalConstPtr &goal)
ros::ServiceServer change_joints_server_
#define ROS_DEBUG_STREAM(args)
bool changeJointsCb(play_motion_builder_msgs::ChangeJoints::Request &req, play_motion_builder_msgs::ChangeJoints::Response &res)
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())
#define ROS_INFO_STREAM(args)
bool sleep() const
#define ROS_ERROR_STREAM(args)
void registerGoalCallback(boost::function< void()> cb)
ros::ServiceServer store_motion_server_
bool listJointGroupsCb(play_motion_builder_msgs::ListJointGroups::Request &req, play_motion_builder_msgs::ListJointGroups::Response &res)
#define ROS_ERROR(...)
ros::ServiceServer edit_motion_server_
std::unique_ptr< Motion > motion_


play_motion_builder
Author(s):
autogenerated on Mon Feb 28 2022 23:13:39