interactive_roi_selection.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 Roboception GmbH
3  *
4  * Author: Carlos Xavier Garcia Briones
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * 3. Neither the name of the copyright holder nor the names of its contributors
17  * may be used to endorse or promote products derived from this software without
18  * specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
33 
34 #include <rc_pick_client/SetRegionOfInterest.h>
35 #include <rc_pick_client/GetRegionsOfInterest.h>
36 
38 {
40 {
41  nh_ = std::make_shared<ros::NodeHandle>();
42  server_.reset(new interactive_markers::InteractiveMarkerServer("rc_roi_manager_gui", "", true));
43  ros::Duration(0.1).sleep();
44 }
45 
47 {
48  ROS_INFO("Disconnecting the interactive region of interest server..");
49  server_.reset();
50 }
51 
53 {
54  tf::Vector3 u(q.x(), q.y(), q.z());
55  double w = q.w();
56  rot_v = 2.0f * u.dot(v) * u + (w * w - u.dot(u)) * v + 2.0f * w * u.cross(v);
57 }
58 
60  const visualization_msgs::InteractiveMarkerFeedbackConstPtr& feedback)
61 {
62  ROS_DEBUG_STREAM(feedback->marker_name << " is now at " << feedback->pose.position.x << ", "
63  << feedback->pose.position.y << ", " << feedback->pose.position.z);
64 
65  visualization_msgs::InteractiveMarker corner_int_marker;
66  server_->get("corner_0", corner_int_marker);
67 
68  geometry_msgs::Pose corner_pose;
69 
70  if (corner_int_marker.pose.orientation.w == 0)
71  corner_int_marker.pose.orientation.w = 1;
72 
73  // Find out if a rotation has taken place
74  double orientation_change = (feedback->pose.orientation.x + feedback->pose.orientation.y +
75  feedback->pose.orientation.z + feedback->pose.orientation.w) -
76  (corner_int_marker.pose.orientation.x + corner_int_marker.pose.orientation.y +
77  corner_int_marker.pose.orientation.z + corner_int_marker.pose.orientation.w);
78  if (orientation_change < 0)
79  orientation_change *= -1;
80  bool center_has_rotated = (orientation_change > 0.001);
81 
82  corner_pose.orientation = feedback->pose.orientation;
83  // Calculate new corner position due to rotation
84  if (center_has_rotated)
85  {
86  tf::Quaternion q_center, q_corner;
87  tf::quaternionMsgToTF(corner_int_marker.pose.orientation, q_corner);
88  tf::quaternionMsgToTF(feedback->pose.orientation, q_center);
89  // Compute rotation quaternion
90  tf::Quaternion rot_quaternion = q_center * q_corner.inverse();
91 
92  // Move corner back to its relative position
93  tf::Vector3 transf_position;
94  tf::Vector3 translation_corner_to_center(corner_int_marker.pose.position.x - feedback->pose.position.x,
95  corner_int_marker.pose.position.y - feedback->pose.position.y,
96  corner_int_marker.pose.position.z - feedback->pose.position.z);
97  computeVectorRotation(translation_corner_to_center, rot_quaternion, transf_position);
98  corner_pose.position.x = transf_position.x() + feedback->pose.position.x;
99  corner_pose.position.y = transf_position.y() + feedback->pose.position.y;
100  corner_pose.position.z = transf_position.z() + feedback->pose.position.z;
101 
102  ROS_DEBUG_STREAM("center quaternion: " << q_center.x() << "," << q_center.y() << "," << q_center.z() << ","
103  << q_center.w());
104  ROS_DEBUG_STREAM("corner quaternion: " << q_corner.x() << "," << q_corner.y() << "," << q_corner.z() << ","
105  << q_corner.w());
106  ROS_DEBUG_STREAM("rotation quaternion: " << rot_quaternion.x() << "," << rot_quaternion.y() << ","
107  << rot_quaternion.z() << "," << rot_quaternion.w());
108  }
109  else
110  {
111  // Corner position has to be updated
112  corner_pose.position.x = corner_int_marker.pose.position.x + feedback->pose.position.x - center_position_.x();
113  corner_pose.position.y = corner_int_marker.pose.position.y + feedback->pose.position.y - center_position_.y();
114  corner_pose.position.z = corner_int_marker.pose.position.z + feedback->pose.position.z - center_position_.z();
115  }
116  server_->setPose("corner_0", corner_pose);
117  server_->applyChanges();
118 
119  // Saving the present center position to compute the future displacement of the center
120  tf::quaternionMsgToTF(corner_pose.orientation, center_orientation_);
121  tf::pointMsgToTF(feedback->pose.position, center_position_);
122 
123  ROS_DEBUG_STREAM("corner_0"
124  << " is now at " << corner_pose.position.x << ", " << corner_pose.position.y << ", "
125  << corner_pose.position.z);
126 }
127 
129  const visualization_msgs::InteractiveMarkerFeedbackConstPtr& feedback)
130 {
131  tf::Vector3 position;
132  tf::pointMsgToTF(feedback->pose.position, position);
133  float radius = (position - center_position_).length();
134  dimensions_ = tf::Vector3(radius, radius, radius);
136 }
137 
139 {
140  server_->erase("center");
142  server_->applyChanges();
143 }
144 
146  const visualization_msgs::InteractiveMarkerFeedbackConstPtr& feedback)
147 {
148  ROS_DEBUG_STREAM(feedback->marker_name << " is now at " << feedback->pose.position.x << ", "
149  << feedback->pose.position.y << ", " << feedback->pose.position.z);
150  tf::Vector3 present_dimensions(feedback->pose.position.x - center_position_.x(),
151  feedback->pose.position.y - center_position_.y(),
152  feedback->pose.position.z - center_position_.z());
153 
154  // Compute rotated dimensions of the box
156  dimensions_ = dimensions_.absolute();
157 
159 }
160 
161 // Generate marker box
162 visualization_msgs::Marker InteractiveRoiSelection::makeMarker(tf::Vector3 box_dimensions, bool is_center)
163 {
164  visualization_msgs::Marker marker;
165 
166  marker.type = interactive_roi_.primitive.type;
167 
168  if (is_center)
169  {
170  float center_scale = 2;
171  marker.scale.x = center_scale * box_dimensions.x();
172  marker.scale.y = center_scale * box_dimensions.y();
173  marker.scale.z = center_scale * box_dimensions.z();
174  marker.color.r = 150 / 255.0;
175  marker.color.g = 104 / 2;
176  marker.color.b = 251 / 255.0;
177  marker.color.a = 0.3;
178  }
179  else
180  {
181  marker.scale.x = box_dimensions.x();
182  marker.scale.y = box_dimensions.y();
183  marker.scale.z = box_dimensions.z();
184  marker.color.r = 255 / 255.0;
185  marker.color.g = 204 / 2;
186  marker.color.b = 0 / 255.0;
187  marker.color.a = 1.0;
188  }
189 
190  return marker;
191 }
192 
193 void InteractiveRoiSelection::makeSphereControls(visualization_msgs::InteractiveMarker& interactive_marker,
194  bool is_center)
195 {
196  // Add controls for axis rotation and positioning
197  if (is_center)
198  {
199  visualization_msgs::InteractiveMarkerControl control;
200  control.orientation_mode = visualization_msgs::InteractiveMarkerControl::FIXED;
201  control.orientation.w = 1;
202  control.orientation.x = 1;
203  control.orientation.y = 0;
204  control.orientation.z = 0;
205  control.name = "move_x";
206  control.interaction_mode = visualization_msgs::InteractiveMarkerControl::MOVE_AXIS;
207  interactive_marker.controls.push_back(control);
208 
209  control.name = "move_y";
210  control.orientation.w = 1;
211  control.orientation.x = 0;
212  control.orientation.y = 1;
213  control.orientation.z = 0;
214  control.interaction_mode = visualization_msgs::InteractiveMarkerControl::MOVE_AXIS;
215  interactive_marker.controls.push_back(control);
216 
217  control.name = "move_z";
218  control.orientation.w = 1;
219  control.orientation.x = 0;
220  control.orientation.y = 0;
221  control.orientation.z = 1;
222  control.interaction_mode = visualization_msgs::InteractiveMarkerControl::MOVE_AXIS;
223  interactive_marker.controls.push_back(control);
224  }
225  else
226  {
227  // Rotate corner marker orientation 45 degrees on the y-Axis.
228  visualization_msgs::InteractiveMarkerControl control;
229  control.orientation_mode = visualization_msgs::InteractiveMarkerControl::FIXED;
230  control.orientation.w = 0.923879468105164;
231  control.orientation.x = 0;
232  control.orientation.y = 0.382683587855188;
233  control.orientation.z = 0;
234  control.name = "move_x";
235  control.interaction_mode = visualization_msgs::InteractiveMarkerControl::MOVE_AXIS;
236  interactive_marker.controls.push_back(control);
237  }
238 }
239 
240 // Generate interactive markers
241 void InteractiveRoiSelection::makeBoxControls(visualization_msgs::InteractiveMarker& interactive_marker, bool is_center)
242 {
243  // Add controls for axis rotation and positioning
244 
245  visualization_msgs::InteractiveMarkerControl control;
246  control.orientation_mode = visualization_msgs::InteractiveMarkerControl::INHERIT;
247  control.orientation.w = 1;
248  control.orientation.x = 1;
249  control.orientation.y = 0;
250  control.orientation.z = 0;
251  control.name = "move_x";
252  control.interaction_mode = visualization_msgs::InteractiveMarkerControl::MOVE_AXIS;
253  interactive_marker.controls.push_back(control);
254  if (is_center)
255  {
256  control.name = "rotate_x";
257  control.interaction_mode = visualization_msgs::InteractiveMarkerControl::ROTATE_AXIS;
258  interactive_marker.controls.push_back(control);
259  }
260 
261  control.name = "move_y";
262  control.orientation.w = 1;
263  control.orientation.x = 0;
264  control.orientation.y = 1;
265  control.orientation.z = 0;
266  control.interaction_mode = visualization_msgs::InteractiveMarkerControl::MOVE_AXIS;
267  interactive_marker.controls.push_back(control);
268  if (is_center)
269  {
270  control.name = "rotate_y";
271  control.interaction_mode = visualization_msgs::InteractiveMarkerControl::ROTATE_AXIS;
272  interactive_marker.controls.push_back(control);
273  }
274 
275  control.name = "move_z";
276  control.orientation.w = 1;
277  control.orientation.x = 0;
278  control.orientation.y = 0;
279  control.orientation.z = 1;
280  control.interaction_mode = visualization_msgs::InteractiveMarkerControl::MOVE_AXIS;
281  interactive_marker.controls.push_back(control);
282 
283  if (is_center)
284  {
285  control.name = "rotate_z";
286  control.interaction_mode = visualization_msgs::InteractiveMarkerControl::ROTATE_AXIS;
287  interactive_marker.controls.push_back(control);
288  }
289 }
290 
291 // Generate interactive markers
292 void InteractiveRoiSelection::makeInteractiveMarker(std::string int_marker_name, std::string int_marker_description,
293  const tf::Vector3& position, bool is_center,
294  tf::Vector3 box_dimensions, tf::Quaternion box_orientation)
295 {
296  visualization_msgs::InteractiveMarker int_marker;
297  int_marker.header.frame_id = interactive_roi_.pose.header.frame_id;
298  tf::pointTFToMsg(position, int_marker.pose.position);
299  tf::quaternionTFToMsg(box_orientation, int_marker.pose.orientation);
300  int_marker.scale = 1.7 * box_dimensions[box_dimensions.maxAxis()];
301 
302  int_marker.name = int_marker_name;
303  int_marker.description = int_marker_description;
304 
305  // insert a marker
306  visualization_msgs::InteractiveMarkerControl control;
307  control.always_visible = is_center;
308  control.markers.push_back(makeMarker(box_dimensions, is_center));
309  control.interaction_mode = visualization_msgs::InteractiveMarkerControl::NONE;
310  int_marker.controls.push_back(control);
311  int_marker.controls.back();
312 
313  if (interactive_roi_.primitive.type == shape_msgs::SolidPrimitive::Type::BOX)
314  {
315  makeBoxControls(int_marker, is_center);
316  server_->insert(int_marker);
317  if (is_center)
318  {
319  server_->setCallback(int_marker.name, boost::bind(&InteractiveRoiSelection::processRoiPoseFeedback, this, _1));
320  }
321  else
322  {
323  server_->setCallback(int_marker.name, boost::bind(&InteractiveRoiSelection::processRoiSizeFeedback, this, _1));
324  }
325  }
326  else if (interactive_roi_.primitive.type == shape_msgs::SolidPrimitive::Type::SPHERE)
327  {
328  makeSphereControls(int_marker, is_center);
329  server_->insert(int_marker);
330  if (is_center)
331  {
332  server_->setCallback(int_marker.name, boost::bind(&InteractiveRoiSelection::processRoiPoseFeedback, this, _1));
333  }
334  else
335  {
336  server_->setCallback(int_marker.name, boost::bind(&InteractiveRoiSelection::processSphereSizeFeedback, this, _1));
337  }
338  }
339  else
340  {
341  ROS_FATAL("The provided shape is currently not supported.");
342  }
343 }
344 
345 bool InteractiveRoiSelection::setInteractiveRoi(const rc_pick_client::RegionOfInterest& roi)
346 {
347  interactive_roi_ = roi;
350  tf::Vector3 corner_position_rot;
351  if (interactive_roi_.primitive.type == shape_msgs::SolidPrimitive::Type::BOX)
352  {
353  dimensions_ =
354  tf::Vector3(interactive_roi_.primitive.dimensions[0] / 2, interactive_roi_.primitive.dimensions[1] / 2,
355  interactive_roi_.primitive.dimensions[2] / 2);
356 
357  // Rotate corner marker position with the roi orientation.
359  }
360  else if (interactive_roi_.primitive.type == shape_msgs::SolidPrimitive::Type::SPHERE)
361  {
362  dimensions_ = tf::Vector3(interactive_roi_.primitive.dimensions[0], interactive_roi_.primitive.dimensions[0],
363  interactive_roi_.primitive.dimensions[0]);
364 
365  // Rotate corner marker position 45 degrees on the y-Axis.
366  corner_position_rot = tf::Vector3(dimensions_.x(), 0, 0);
367  computeVectorRotation(corner_position_rot, tf::Quaternion(0, 0.382683587855188, 0, 0.923879468105164),
368  corner_position_rot);
369  }
370  else
371  {
372  ROS_ERROR_STREAM("An unsupported primitive was used.");
373  return false;
374  }
375 
377  makeInteractiveMarker("corner_0", "Size", center_position_ + corner_position_rot, false,
378  tf::Vector3(0.02, 0.02, 0.02), center_orientation_);
379 
380  server_->applyChanges();
381  return true;
382 }
383 
384 bool InteractiveRoiSelection::getInteractiveRoi(rc_pick_client::RegionOfInterest& roi)
385 {
386  if (interactive_roi_.primitive.type == shape_msgs::SolidPrimitive::Type::BOX)
387  {
388  dimensions_ = dimensions_ * 2;
389  }
392 
393  interactive_roi_.primitive.dimensions[0] = dimensions_.x();
394  interactive_roi_.primitive.dimensions[1] = dimensions_.y();
395  interactive_roi_.primitive.dimensions[2] = dimensions_.z();
396  roi = interactive_roi_;
397  server_->clear();
398  server_->applyChanges();
399  return true;
400 }
401 
402 } // namespace rc_roi_manager_gui
#define ROS_FATAL(...)
static void pointMsgToTF(const geometry_msgs::Point &msg_v, Point &bt_v)
bool getInteractiveRoi(rc_pick_client::RegionOfInterest &roi)
Provides the region of interest from the server.
f
void makeSphereControls(visualization_msgs::InteractiveMarker &interactive_marker, bool is_center)
Generate controls of a sphere interactive marker.
void updateCenterMarker()
Update the center interactive marker in rviz.
bool sleep() const
TFSIMD_FORCE_INLINE int maxAxis() const
void processSphereSizeFeedback(const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback)
Process changes on the region of interest&#39;s size.
void computeVectorRotation(const tf::Vector3 &v, const tf::Quaternion &q, tf::Vector3 &rot_v)
Compute the rotation of a vector by a quaternion.
TFSIMD_FORCE_INLINE const tfScalar & x() const
boost::shared_ptr< interactive_markers::InteractiveMarkerServer > server_
void processRoiPoseFeedback(const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback)
Process changes on the position and rotation of the region of interest.
TFSIMD_FORCE_INLINE tfScalar dot(const Vector3 &v) const
TFSIMD_FORCE_INLINE const tfScalar & z() const
static void quaternionMsgToTF(const geometry_msgs::Quaternion &msg, Quaternion &bt)
#define ROS_INFO(...)
bool setInteractiveRoi(const rc_pick_client::RegionOfInterest &roi)
Sets a new region of interest in the server.
static void quaternionTFToMsg(const Quaternion &bt, geometry_msgs::Quaternion &msg)
TFSIMD_FORCE_INLINE const tfScalar & y() const
void makeBoxControls(visualization_msgs::InteractiveMarker &interactive_marker, bool is_center)
Generate controls of a box interactive marker.
#define ROS_DEBUG_STREAM(args)
Quaternion inverse() const
TFSIMD_FORCE_INLINE const tfScalar & w() const
TFSIMD_FORCE_INLINE Vector3 absolute() const
visualization_msgs::Marker makeMarker(tf::Vector3 box_dimensions, bool is_center)
Generate a marker.
void makeInteractiveMarker(std::string int_marker_name, std::string int_marker_description, const tf::Vector3 &position, bool is_center, tf::Vector3 box_dimensions, tf::Quaternion box_orientation)
Generate an interactive marker.
rc_pick_client::RegionOfInterest interactive_roi_
TFSIMD_FORCE_INLINE tfScalar length(const Quaternion &q)
#define ROS_ERROR_STREAM(args)
void processRoiSizeFeedback(const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback)
Process changes on the region of interest&#39;s size.
static void pointTFToMsg(const Point &bt_v, geometry_msgs::Point &msg_v)


rc_roi_manager_gui
Author(s): Carlos Xavier Garcia Briones
autogenerated on Sat Feb 13 2021 03:42:01