Robowflex  v0.1
Making MoveIt Easy
services.cpp
Go to the documentation of this file.
1 /* Author: Zachary Kingston */
2 
3 #include <moveit_msgs/ApplyPlanningScene.h>
4 #include <moveit_msgs/ExecuteTrajectoryGoal.h>
5 #include <moveit_msgs/ExecuteTrajectoryResult.h>
6 #include <moveit_msgs/GetPlanningScene.h>
7 #include <std_srvs/Empty.h>
8 
9 #include <robowflex_library/io.h>
11 #include <robowflex_library/log.h>
13 #include <robowflex_library/yaml.h>
14 
16 
17 using namespace robowflex;
18 using namespace robowflex::movegroup;
19 
20 ///
21 /// MoveGroupHelper::Action
22 ///
23 
25 {
27  const auto file = IO::loadFileToYAML(filename);
28 
29  if (!file.first)
30  {
31  RBX_WARN("Failed to open file %s!", filename);
32  return false;
33  }
34 
35  id = file.second["id"].as<std::string>();
36  request = file.second["request"].as<moveit_msgs::MotionPlanRequest>();
37  success = file.second["success"].as<bool>();
38  time = file.second["time"].as<double>();
39 
40  if (IO::isNode(file.second["trajectory"]))
41  trajectory = file.second["trajectory"].as<moveit_msgs::RobotTrajectory>();
42 
43  return true;
44 }
45 
47 {
48  YAML::Node node;
49 
50  node["id"] = id;
51 
52  moveit_msgs::PlanningScene scene_msg;
53  scene->getSceneConst()->getPlanningSceneMsg(scene_msg);
54  node["scene"] = IO::toNode(scene_msg);
55 
56  node["request"] = IO::toNode(request);
57  node["success"] = success ? "true" : "false";
58  node["time"] = time;
59  node["trajectory"] = IO::toNode(trajectory);
60 
61  return IO::YAMLToFile(node, filename);
62 }
63 
64 ///
65 /// MoveGroupHelper
66 ///
67 
68 const std::string MoveGroupHelper::MOVE_GROUP{"/move_group"};
69 const std::string MoveGroupHelper::GET_SCENE{"get_planning_scene"};
70 const std::string MoveGroupHelper::APPLY_SCENE{"apply_planning_scene"};
71 const std::string MoveGroupHelper::CLEAR_OCTOMAP{"clear_octomap"};
72 const std::string MoveGroupHelper::EXECUTE{"/execute_trajectory"};
73 
75  : nh_("/")
76  , goal_sub_(nh_.subscribe(move_group + "/goal", 10, &MoveGroupHelper::moveGroupGoalCallback, this))
77  , result_sub_(nh_.subscribe(move_group + "/result", 10, &MoveGroupHelper::moveGroupResultCallback, this))
78  , gpsc_(nh_.serviceClient<moveit_msgs::GetPlanningScene>(GET_SCENE, true))
79  , apsc_(nh_.serviceClient<moveit_msgs::ApplyPlanningScene>(APPLY_SCENE, true))
80  , co_(nh_.serviceClient<std_srvs::Empty>(CLEAR_OCTOMAP, true))
81  , eac_(nh_, EXECUTE, true)
82  , robot_(std::make_shared<ParamRobot>())
83 {
84  RBX_INFO("Waiting for %s to connect...", EXECUTE);
85  eac_.waitForServer();
86  RBX_INFO("%s connected!", EXECUTE);
87  RBX_INFO("Waiting for %s to connect...", GET_SCENE);
88  gpsc_.waitForExistence();
89  RBX_INFO("%s connected!", GET_SCENE);
90  RBX_INFO("Waiting for %s to connect...", APPLY_SCENE);
91  apsc_.waitForExistence();
92  RBX_INFO("%s connected!", APPLY_SCENE);
93  RBX_INFO("Waiting for %s to connect...", CLEAR_OCTOMAP);
94  co_.waitForExistence();
95  RBX_INFO("%s connected!", CLEAR_OCTOMAP);
96 }
97 
99 {
100  goal_sub_.shutdown();
101  result_sub_.shutdown();
102  gpsc_.shutdown();
103  apsc_.shutdown();
104  co_.shutdown();
105 }
106 
108 {
110 }
111 
113 {
114  if (!eac_.isServerConnected())
115  return false;
116 
117  moveit_msgs::ExecuteTrajectoryGoal goal;
118 
119  // Check if a Trajectory is time parameterized, with some goofiness for indigo.
120 #if ROBOWFLEX_AT_LEAST_KINETIC
121  double value = path.getWayPointDurationFromStart(path.getWayPointCount());
122 #else
123  double value = path.getWaypointDurationFromStart(path.getWayPointCount());
124 #endif
125 
126  if (value == 0)
127  {
128  RBX_ERROR("Trajectory is not parameterized and cannot be executed! did you use "
129  "Trajectory::computeTimeParameterization?");
130  return false;
131  }
132 
133  path.getRobotTrajectoryMsg(goal.trajectory);
134 
135  eac_.sendGoal(goal);
136  if (!eac_.waitForResult())
137  RBX_INFO("ExecuteTrajectory action returned early");
138 
139  return eac_.getState() == actionlib::SimpleClientGoalState::SUCCEEDED;
140 }
141 
143 {
144  moveit_msgs::GetPlanningScene::Request request;
145  moveit_msgs::GetPlanningScene::Response response;
146  request.components.components = moveit_msgs::PlanningSceneComponents::ROBOT_STATE |
147  moveit_msgs::PlanningSceneComponents::ROBOT_STATE_ATTACHED_OBJECTS;
148 
149  if (gpsc_.call(request, response))
150  {
151  robot->setState(response.scene.robot_state);
152  return true;
153  }
154 
155  return false;
156 }
157 
159 {
160  moveit_msgs::GetPlanningScene::Request request;
161  moveit_msgs::GetPlanningScene::Response response;
162  request.components.components = moveit_msgs::PlanningSceneComponents::SCENE_SETTINGS |
163  moveit_msgs::PlanningSceneComponents::ROBOT_STATE |
164  moveit_msgs::PlanningSceneComponents::ROBOT_STATE_ATTACHED_OBJECTS |
165  moveit_msgs::PlanningSceneComponents::WORLD_OBJECT_NAMES |
166  moveit_msgs::PlanningSceneComponents::WORLD_OBJECT_GEOMETRY |
167  moveit_msgs::PlanningSceneComponents::OCTOMAP |
168  moveit_msgs::PlanningSceneComponents::TRANSFORMS |
169  moveit_msgs::PlanningSceneComponents::ALLOWED_COLLISION_MATRIX |
170  moveit_msgs::PlanningSceneComponents::LINK_PADDING_AND_SCALING |
171  moveit_msgs::PlanningSceneComponents::OBJECT_COLORS;
172 
173  if (gpsc_.call(request, response))
174  {
175  scene->useMessage(response.scene);
176  return true;
177  }
178 
179  return false;
180 }
181 
183 {
184  moveit_msgs::ApplyPlanningScene::Request request;
185  moveit_msgs::ApplyPlanningScene::Response response;
186  request.scene = scene->getMessage();
187 
188  return apsc_.call(request, response);
189 }
190 
192 {
193  std_srvs::EmptyRequest request;
194  std_srvs::EmptyResponse response;
195 
196  return co_.call(request, response);
197 }
198 
199 void MoveGroupHelper::moveGroupGoalCallback(const moveit_msgs::MoveGroupActionGoal &msg)
200 {
201  const std::string &id = msg.goal_id.id;
202  RBX_DEBUG("Intercepted request goal ID: `%s`", id);
203 
204  Action action;
205  action.scene.reset(new Scene(robot_));
206  pullScene(action.scene);
207  action.scene->useMessage(msg.goal.planning_options.planning_scene_diff);
208  action.request = msg.goal.request;
209 
210  requests_.emplace(id, action);
211 }
212 
213 void MoveGroupHelper::moveGroupResultCallback(const moveit_msgs::MoveGroupActionResult &msg)
214 {
215  const std::string &id = msg.status.goal_id.id;
216 
217  auto request = requests_.find(id);
218  if (request == requests_.end())
219  {
220  RBX_WARN("Intercepted unknown request response ID: `%s`", id);
221  return;
222  }
223 
224  RBX_DEBUG("Intercepted request response ID: `%s`", id);
225 
226  Action &action = request->second;
227  action.id = id;
228  action.success = msg.result.error_code.val == moveit_msgs::MoveItErrorCodes::SUCCESS;
229  action.time = msg.result.planning_time;
230  action.trajectory = msg.result.planned_trajectory;
231 
232  if (callback_)
233  callback_(action);
234 
235  requests_.erase(request);
236 }
MOVEIT_DEPRECATED double getWaypointDurationFromStart(std::size_t index) const
double getWayPointDurationFromStart(std::size_t index) const
std::size_t getWayPointCount() const
void getRobotTrajectoryMsg(moveit_msgs::RobotTrajectory &trajectory) const
Loads information about a robot from the parameter server.
A shared pointer wrapper for robowflex::Robot.
A const shared pointer wrapper for robowflex::Scene.
A shared pointer wrapper for robowflex::Scene.
Wrapper class around the planning scene and collision geometry.
Definition: scene.h:48
A helper class that allows for pulling and pushing of scenes, robots, and trajectories to move group.
Definition: services.h:27
static const std::string EXECUTE
Name of execute trajectory service.
Definition: services.h:131
MoveGroupHelper(const std::string &move_group=MOVE_GROUP)
Constructor. Sets up service clients.
Definition: services.cpp:74
bool pushScene(const SceneConstPtr &scene)
Pushes the current planning scene to move group.
Definition: services.cpp:182
ResultCallback callback_
Callback function for move group results.
Definition: services.h:121
ros::ServiceClient gpsc_
Get planning scene service.
Definition: services.h:114
RobotPtr robot_
Robot on the parameter server used by move group.
Definition: services.h:125
ros::ServiceClient co_
Clear octomap service.
Definition: services.h:116
void moveGroupGoalCallback(const moveit_msgs::MoveGroupActionGoal &msg)
Callback function for a move group goal.
Definition: services.cpp:199
bool executeTrajectory(const robot_trajectory::RobotTrajectory &path)
Executes a planned trajectory through move group.
Definition: services.cpp:112
ros::Subscriber result_sub_
Move group result subscriber.
Definition: services.h:113
ros::Subscriber goal_sub_
Move group goal subscriber.
Definition: services.h:112
void setResultCallback(const ResultCallback &callback)
Sets a callback function that is called whenever a motion plan request is serviced by move group.
Definition: services.cpp:107
void moveGroupResultCallback(const moveit_msgs::MoveGroupActionResult &msg)
Callback function for a move group result.
Definition: services.cpp:213
bool pullScene(ScenePtr scene)
Pulls the current planning scene from move group.
Definition: services.cpp:158
~MoveGroupHelper()
Destructor. Cleans up services.
Definition: services.cpp:98
bool pullState(RobotPtr robot)
Pulls the current robot state from move group.
Definition: services.cpp:142
ros::NodeHandle nh_
Node handle.
Definition: services.h:111
static const std::string CLEAR_OCTOMAP
Name of clear octomap service.
Definition: services.h:130
actionlib::SimpleActionClient< moveit_msgs::ExecuteTrajectoryAction > eac_
Definition: services.h:118
static const std::string GET_SCENE
Name of get scene service.
Definition: services.h:128
std::map< std::string, Action > requests_
Move group requests.
Definition: services.h:123
static const std::string APPLY_SCENE
Name of apply scene service.
Definition: services.h:129
static const std::string MOVE_GROUP
Name of move_group namespace.
Definition: services.h:127
ros::ServiceClient apsc_
Apply planning scene service.
Definition: services.h:115
bool clearOctomap()
Clears the octomap in the planning scene of the movegroup.
Definition: services.cpp:191
#define RBX_WARN(fmt,...)
Output a warning logging message.
Definition: log.h:110
#define RBX_ERROR(fmt,...)
Output a error logging message.
Definition: log.h:102
#define RBX_INFO(fmt,...)
Output a info logging message.
Definition: log.h:118
#define RBX_DEBUG(fmt,...)
Output a debug logging message.
Definition: log.h:126
Functions for loading and animating robots in Blender.
bool YAMLToFile(const YAML::Node &node, const std::string &file)
Write the contents of a YAML node out to a potentially new file.
bool isNode(const YAML::Node &node)
Checks if a key exists within a YAML node.
Definition: yaml.cpp:1847
std::pair< bool, YAML::Node > loadFileToYAML(const std::string &path)
Loads a file to a YAML node.
YAML::Node toNode(const geometry_msgs::Pose &msg)
Converts a pose message to YAML.
Definition: yaml.cpp:1874
Move group interaction related classes and features.
Definition: services.h:22
Main namespace. Contains all library classes and functions.
Definition: scene.cpp:25
Functions for loading and animating scenes in Blender.
A container struct for all relevant information about a motion planning request to move group.
Definition: services.h:33
moveit_msgs::MotionPlanRequest request
Motion planning request.
Definition: services.h:36
bool toYAMLFile(const std::string &filename)
Save a recorded action to a YAML file.
Definition: services.cpp:46
bool fromYAMLFile(const std::string &filename)
Load a recorded action from a YAML file.
Definition: services.cpp:24
ScenePtr scene
Scene used for planning.
Definition: services.h:35
moveit_msgs::RobotTrajectory trajectory
Planned trajectory on success.
Definition: services.h:39
void callback(movegroup::MoveGroupHelper::Action &action)
Definition: tapedeck.cpp:20
robot_trajectory::RobotTrajectory trajectory(rmodel,"right_arm")