interactive_manipulation_action_server.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015, Jorge Santos
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Willow Garage, Inc. nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  * Author: Jorge Santos
30  */
31 
32 #include <ros/ros.h>
33 
34 // interactive manipulation markers action server
37 
38 #include <turtlebot_arm_object_manipulation/InteractiveManipAction.h>
39 
40 // auxiliary libraries
43 
44 // MoveIt!
45 #include <moveit_msgs/CollisionObject.h>
47 
48 
49 using namespace visualization_msgs;
50 
51 
53 {
54 
56 {
57 private:
59 
61 
63  std::string action_name_;
64 
65  geometry_msgs::Pose old_pose_;
66 
67  turtlebot_arm_object_manipulation::InteractiveManipFeedback feedback_;
68  turtlebot_arm_object_manipulation::InteractiveManipResult result_;
69  turtlebot_arm_object_manipulation::InteractiveManipGoalConstPtr goal_;
70 
71  // We use the planning_scene_interface::PlanningSceneInterface to retrieve world objects
73 
74 public:
75 
76  InteractiveManipulationServer(const std::string name) :
77  nh_("~"), server_("move_objects"), as_(name, false), action_name_(name)
78  {
79  // Register the goal and feedback callbacks.
80  as_.registerGoalCallback(boost::bind(&InteractiveManipulationServer::goalCB, this));
81  as_.registerPreemptCallback(boost::bind(&InteractiveManipulationServer::preemptCB, this));
82 
83  as_.start();
84  }
85 
86  void goalCB()
87  {
88  // accept the new goal
89  goal_ = as_.acceptNewGoal();
90 
91  ROS_INFO("[interactive manip] Received goal! Adding markers for objects in the word other than the table");
92  addObjects();
93  }
94 
95  void preemptCB()
96  {
97  ROS_WARN("[interactive manip] %s: Preempted", action_name_.c_str());
98  // set the action state to preempted
99  as_.setPreempted();
100  }
101 
102  // Moving an object; keep MOUSE_DOWN pose (origin) and move the object to MOUSE_UP pose
103  void feedbackCb(const InteractiveMarkerFeedbackConstPtr &feedback)
104  {
105  if (!as_.isActive())
106  {
107  ROS_INFO("[interactive manip] Got feedback but not active!");
108  return;
109  }
110  switch (feedback->event_type)
111  {
112  case visualization_msgs::InteractiveMarkerFeedback::MOUSE_DOWN:
113  ROS_INFO_STREAM("[interactive manip] Staging '" << feedback->marker_name << "' at " << feedback->pose);
114  old_pose_ = feedback->pose;
115  break;
116 
117  case visualization_msgs::InteractiveMarkerFeedback::MOUSE_UP:
118  ROS_INFO_STREAM("[interactive manip] Now moving '" << feedback->marker_name << "' to " << feedback->pose);
119  moveObject(feedback->marker_name, feedback->header, old_pose_, feedback->pose);
120  break;
121  }
122 
123  server_.applyChanges();
124  }
125 
126  void moveObject(const std::string& marker_name, const std_msgs::Header& poses_header,
127  const geometry_msgs::Pose& start_pose, const geometry_msgs::Pose& end_pose)
128  {
129  result_.header = poses_header;
130  result_.obj_name = marker_name;
131  result_.pick_pose = start_pose;
132  result_.place_pose = end_pose;
133 
134  as_.setSucceeded(result_);
135 
136  server_.clear();
137  server_.applyChanges();
138  }
139 
140  // Add an interactive marker for any object in the word other than the table
141  void addObjects()
142  {
143  server_.clear();
144  server_.applyChanges();
145 
146  bool active = as_.isActive();
147 
148  std::map<std::string, moveit_msgs::CollisionObject> objects =
149  planning_scene_interface_.getObjects(planning_scene_interface_.getKnownObjectNames());
150  for (const std::pair<std::string, moveit_msgs::CollisionObject>& obj: objects)
151  {
152  if (obj.first != "table")
153  {
154  addMarker(obj.second, active);
155  }
156  }
157 
158  server_.applyChanges();
159  }
160 
161  // Add an interactive marker for the given object
162  bool addMarker(const moveit_msgs::CollisionObject& obj, bool active)
163  {
164  InteractiveMarker marker;
165  marker.header = obj.header;
166  marker.name = obj.id;
167 
168  // We get object's pose from the mesh/primitive poses; try first with the meshes
169  if (obj.mesh_poses.size() > 0)
170  {
171  marker.pose = obj.mesh_poses[0];
172  if (obj.meshes.size() > 0)
173  {
174  Eigen::Vector3d obj_size = shapes::computeShapeExtents(obj.meshes[0]);
175 
176  // We use the biggest dimension of the mesh to scale the marker
177  marker.scale = obj_size.maxCoeff();
178 
179  // We assume meshes laying in the floor (well, table), so we bump up marker pose by half z-dimension
180  marker.pose.position.z += obj_size[2]/2.0;
181  }
182  else
183  {
184  ROS_ERROR("[interactive manip] Collision object has no meshes");
185  return false;
186  }
187  }
188  else if (obj.primitive_poses.size() > 0)
189  {
190  marker.pose = obj.primitive_poses[0];
191  if (obj.primitives.size() > 0)
192  {
193  // We use the biggest dimension of the primitive to scale the marker
194  marker.scale = shapes::computeShapeExtents(obj.primitives[0]).maxCoeff();
195  }
196  else
197  {
198  ROS_ERROR("[interactive manip] Collision object has no primitives");
199  return false;
200  }
201  }
202  else
203  {
204  ROS_ERROR("[interactive manip] Collision object has no mesh/primitive poses");
205  return false;
206  }
207 
208  InteractiveMarkerControl control;
209  control.orientation.w = 1;
210  control.orientation.x = 0;
211  control.orientation.y = 1;
212  control.orientation.z = 0;
213  control.interaction_mode = InteractiveMarkerControl::MOVE_PLANE;
214 
215  if (active)
216  marker.controls.push_back(control);
217 
218  control.markers.push_back(makeBox(marker, 0.5, 0.5, 0.5));
219  control.markers.push_back(makeLabel(marker, 0.5, 0.5, 0.5));
220  control.always_visible = true;
221  marker.controls.push_back(control);
222 
223  server_.insert(marker);
224  server_.setCallback(marker.name, boost::bind(&InteractiveManipulationServer::feedbackCb, this, _1));
225 
226  ROS_INFO("[interactive manip] Added interactive marker for object '%s' at [%s] and scale [%f]",
227  marker.name.c_str(), mtk::pose2str3D(marker.pose).c_str(), marker.scale);
228 
229  return true;
230  }
231 
232  // Make a box containing the object (5% bigger than the biggest dimension)
233  Marker makeBox(InteractiveMarker &msg, float r, float g, float b)
234  {
235  Marker m;
236 
237  m.type = Marker::CUBE;
238  m.scale.x = msg.scale + (msg.scale * 0.05);
239  m.scale.y = msg.scale + (msg.scale * 0.05);
240  m.scale.z = msg.scale + (msg.scale * 0.05);
241  m.color.r = r;
242  m.color.g = g;
243  m.color.b = b;
244  m.color.a = 0.1;
245 
246  return m;
247  }
248 
249  // Make a label to show over the box
250  Marker makeLabel(InteractiveMarker &msg, float r, float g, float b)
251  {
252  Marker m;
253 
254  m.type = Marker::TEXT_VIEW_FACING;
255  m.text = msg.name;
256  m.scale.x = 0.035;
257  m.scale.y = 0.035;
258  m.scale.z = 0.035;
259  m.color.r = r;
260  m.color.g = g;
261  m.color.b = b;
262  m.color.a = 0.8;
263 
264  m.pose.position.z = msg.scale/2.0 + 0.025;
265 
266  return m;
267  }
268 
269 };
270 
271 };
272 
273 int main(int argc, char** argv)
274 {
275  // initialize node
276  ros::init(argc, argv, "object_interactive_manip_action_server");
277 
279 
280  ros::spin();
281 
282  return 0;
283 }
284 
boost::shared_ptr< const Goal > acceptNewGoal()
turtlebot_arm_object_manipulation::InteractiveManipGoalConstPtr goal_
turtlebot_arm_object_manipulation::InteractiveManipFeedback feedback_
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
std::map< std::string, moveit_msgs::CollisionObject > getObjects(const std::vector< std::string > &object_ids=std::vector< std::string >())
std::string pose2str3D(const geometry_msgs::Pose &pose)
int main(int argc, char **argv)
#define ROS_WARN(...)
void setSucceeded(const Result &result=Result(), const std::string &text=std::string(""))
ROSCPP_DECL void spin(Spinner &spinner)
Marker makeBox(InteractiveMarker &msg)
void setPreempted(const Result &result=Result(), const std::string &text=std::string(""))
#define ROS_INFO(...)
void registerPreemptCallback(boost::function< void()> cb)
void insert(const visualization_msgs::InteractiveMarker &int_marker)
#define ROS_INFO_STREAM(args)
std::vector< std::string > getKnownObjectNames(bool with_type=false)
bool setCallback(const std::string &name, FeedbackCallback feedback_cb, uint8_t feedback_type=DEFAULT_FEEDBACK_CB)
actionlib::SimpleActionServer< turtlebot_arm_object_manipulation::InteractiveManipAction > as_
void registerGoalCallback(boost::function< void()> cb)
Eigen::Vector3d computeShapeExtents(const ShapeMsg &shape_msg)
#define ROS_ERROR(...)
void moveObject(const std::string &marker_name, const std_msgs::Header &poses_header, const geometry_msgs::Pose &start_pose, const geometry_msgs::Pose &end_pose)


turtlebot_arm_object_manipulation
Author(s): Jorge Santos
autogenerated on Fri Feb 7 2020 03:56:40