MultiRobotGoalSelector.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011, Willow Garage, Inc.
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 
30 #include <OGRE/OgreSceneNode.h>
31 #include <OGRE/OgreSceneManager.h>
32 #include <OGRE/OgreEntity.h>
33 
34 #include <ros/console.h>
35 
38 #include <rviz/mesh_loader.h>
39 #include <rviz/geometry.h>
40 
42 #include <tuw_multi_robot_msgs/RobotGoals.h>
43 #include <tuw_multi_robot_msgs/RobotGoalsArray.h>
44 
45 #include <string>
46 
47 namespace tuw_multi_robot_rviz
48 {
49 
51  : moving_flag_node_(NULL), current_flag_property_(NULL)
52 {
53  shortcut_key_ = 'l';
54  robotCount_ = 0;
55  maxRobots_ = 3;
56 
57  pubGoals_ = nh_.advertise<tuw_multi_robot_msgs::RobotGoalsArray>("goals", 0);
58 }
59 
61 {
62  for (unsigned i = 0; i < flag_nodes_.size(); i++)
63  {
64  scene_manager_->destroySceneNode(flag_nodes_[i]);
65  }
66 }
67 
69 {
70  flag_resource_ = "package://tuw_multi_robot_rviz/media/flag.dae";
71 
72  arrow_.reset(new rviz::Arrow(scene_manager_, NULL, 2.0f, 0.2f, 0.5f, 0.35f));
73  arrow_->setColor(0.0f, 1.0f, 0.0f, 1.0f);
74  arrow_->getSceneNode()->setVisible(false);
75 
76  state_ = state::Position;
77 
79  {
80  ROS_ERROR("MultiRobotGoalSelector: failed to load model resource '%s'.", flag_resource_.c_str());
81  return;
82  }
83 
84  moving_flag_node_ = scene_manager_->getRootSceneNode()->createChildSceneNode();
85  Ogre::Entity *entity = scene_manager_->createEntity(flag_resource_);
86  moving_flag_node_->attachObject(entity);
87  moving_flag_node_->setVisible(false);
88 
89  group_robot_names_ = new rviz::Property("Robot Names");
90  group_robot_goals_ = new rviz::Property("Robot Goals");
91  nr_robots_ = new rviz::IntProperty("No. robtos", 3, "the nr of robots used for planning", nullptr, SLOT(onRobotNrChanged()), this);
92  nr_robots_->setMin(0);
93 
97 
98  currentRobotNr_ = 0;
100 }
101 
103 {
104  if (currentRobotNr_ < nr_robots_->getInt())
105  {
106  for (uint32_t i = 0; i < nr_robots_->getInt() - currentRobotNr_; i++)
107  {
108  if (robot_names_.size() <= currentRobotNr_ + i)
109  {
110  robot_names_.push_back(new rviz::StringProperty("Robot " + QString::number(robot_names_.size()), "robot_" + QString::number(robot_names_.size())));
112  }
113  else
114  {
115  robot_names_[currentRobotNr_ + i]->setHidden(false);
116  }
117  }
118  }
119  else if (currentRobotNr_ > nr_robots_->getInt())
120  {
121  for (uint32_t i = 0; i < currentRobotNr_ - nr_robots_->getInt(); i++)
122  {
123  robot_names_[nr_robots_->getInt() + i]->setHidden(true);
124  }
125  }
126 
128 }
129 
131 {
132  state_ = state::Position;
133 
135 
136  if (robotCount_ >= maxRobots_)
137  {
138  robotCount_ = 0;
139 
140  for (auto &fn : flag_nodes_)
141  {
142  fn->detachAllObjects();
143  fn->removeAndDestroyAllChildren();
145  }
146  flag_nodes_.clear();
147  flag_positions_.clear();
148  arrows_robot2flag_.clear();
149  }
150 
151  if (moving_flag_node_)
152  {
153  moving_flag_node_->setVisible(true);
154 
155  state_ = state::Position;
156  current_flag_property_ = new rviz::VectorProperty("Goal " + QString::number(flag_nodes_.size()));
158  flag_angles_.clear();
160  }
161 }
162 
164 {
165  if (moving_flag_node_)
166  {
167  moving_flag_node_->setVisible(false);
168  state_ = state::Position;
169  delete current_flag_property_;
171  flag_angles_.clear();
172  }
173 }
174 
175 void MultiRobotGoalSelector::make_quaternion(geometry_msgs::Pose::_orientation_type &q, double pitch, double roll, double yaw)
176 {
177  double cy = cos(yaw * 0.5);
178  double sy = sin(yaw * 0.5);
179  double cr = cos(roll * 0.5);
180  double sr = sin(roll * 0.5);
181  double cp = cos(pitch * 0.5);
182  double sp = sin(pitch * 0.5);
183 
184  q.w = cy * cr * cp + sy * sr * sp;
185  q.x = cy * sr * cp - sy * cr * sp;
186  q.y = cy * cr * sp + sy * sr * cp;
187  q.z = sy * cr * cp - cy * sr * sp;
188 }
189 
190 void MultiRobotGoalSelector::make_quaternion(Ogre::Quaternion &q, double pitch, double roll, double yaw)
191 {
192  double cy = cos(yaw * 0.5);
193  double sy = sin(yaw * 0.5);
194  double cr = cos(roll * 0.5);
195  double sr = sin(roll * 0.5);
196  double cp = cos(pitch * 0.5);
197  double sp = sin(pitch * 0.5);
198 
199  q.w = cy * cr * cp + sy * sr * sp;
200  q.x = cy * sr * cp - sy * cr * sp;
201  q.y = cy * cr * sp + sy * sr * cp;
202  q.z = sy * cr * cp - cy * sr * sp;
203 }
204 
206 {
207  if (!moving_flag_node_)
208  {
209  return Render;
210  }
211 
212  Ogre::Vector3 intersection;
213  Ogre::Plane ground_plane(Ogre::Vector3::UNIT_Z, 0.0f);
214 
215  if (event.leftDown())
216  {
218  ground_plane,
219  event.x, event.y, intersection))
220  {
221 
222  moving_flag_node_->setVisible(true);
223  moving_flag_node_->setPosition(intersection);
224  current_flag_property_->setVector(intersection);
225 
226  flag_positions_.push_back(intersection);
227 
228  arrow_->setPosition(intersection);
229  arrow_->getSceneNode()->setVisible(true);
230 
231  state_ = state::Orientation;
232 
233  }
234 
235  } else if (event.type == QEvent::MouseMove && event.left()) {
236  //compute angle in x-y plane
237 
238  Ogre::Vector3 cur_pos;
239  Ogre::Plane ground_plane( Ogre::Vector3::UNIT_Z, 0.0f );
240 
242  ground_plane,
243  event.x, event.y, cur_pos ))
244  {
245  double angle = atan2( cur_pos.y - arrow_->getPosition().y, cur_pos.x - arrow_->getPosition().x );
246 
247  //we need base_orient, since the arrow goes along the -z axis by default (for historical reasons)
248  Ogre::Quaternion orient_x = Ogre::Quaternion( Ogre::Radian(-Ogre::Math::HALF_PI), Ogre::Vector3::UNIT_Y );
249 
250  arrow_->setOrientation( Ogre::Quaternion( Ogre::Radian(angle), Ogre::Vector3::UNIT_Z ) * orient_x );
251 
252  Ogre::Quaternion q_from_angle;
253  make_quaternion(q_from_angle, 0,0, angle);
254  moving_flag_node_->setOrientation(q_from_angle);
255 
256  }
257 
258  } else if (event.leftUp()) {
259 
260  if (state_ == state::Orientation)
261  {
262  //compute angle in x-y plane
263  Ogre::Vector3 cur_pos;
264  Ogre::Plane ground_plane( Ogre::Vector3::UNIT_Z, 0.0f );
266  ground_plane,
267  event.x, event.y, cur_pos ))
268  {
269  double angle = atan2( cur_pos.y - arrow_->getPosition().y, cur_pos.x - arrow_->getPosition().x );
270 
271  Ogre::Quaternion q_from_angle;
272  make_quaternion(q_from_angle, 0,0, angle);
273  makeFlag(current_flag_property_->getVector(), q_from_angle);
274  //current_flag_property_ = new rviz::VectorProperty("Goal " + QString::number(flag_nodes_.size()));
275 
276  //cool stuff here, since unique_ptr only allows 1 ptr count arrow_robot2flag_ will be automatically nullptr after this call
277  arrows_robot2flag_.push_back(std::move(arrow_robot2flag_));
278 
279  flag_angles_.push_back(angle);
280 
282  robotCount_++;
283 
284  arrow_->getSceneNode()->setVisible(false);
285 
286  if (robotCount_ >= maxRobots_) {
287 
288  tuw_multi_robot_msgs::RobotGoalsArray array;
289  for (int i = 0; i < maxRobots_; i++)
290  {
291  Ogre::Vector3 position = flag_positions_[i];
292  tuw_multi_robot_msgs::RobotGoals goals;
293 
294  geometry_msgs::Pose pose;
295  pose.position.x = position.x;
296  pose.position.y = position.y;
297  pose.position.z = 0.0;
298  make_quaternion(pose.orientation, 0, 0, flag_angles_[i]);
299  goals.destinations.push_back(pose);
300  goals.robot_name = robot_names_[i]->getStdString();
301 
302  array.robots.push_back(goals);
303  }
304 
305  array.header.stamp = ros::Time::now();
306  array.header.frame_id = context_->getFixedFrame().toStdString();
307  pubGoals_.publish(array);
308 
309  return Render | Finished;
310  }
311  } // end get point
312 
313  } // end state == Orientation
314 
315  } // end if leftUp()
316  else //if mouse is not clicked just update the moving flag
317  {
319  ground_plane,
320  event.x, event.y, intersection))
321  {
322  moving_flag_node_->setVisible(true);
323  moving_flag_node_->setPosition(intersection);
324  current_flag_property_->setVector(intersection);
325  double length = Ogre::Vector3(0,0,0).distance(intersection);
326 
327  if (!arrow_robot2flag_)
328  {
329 
330  arrow_robot2flag_.reset(new rviz::Arrow(scene_manager_, NULL, length - 0.5f, 0.2f, 0.5f, 0.35f));
331  arrow_robot2flag_->setColor(1.0f, 0.0f, 0.0f, 1.0f);
332  //TODO: replace position (0,0,0) with correct robot position and set visibility to true
333  arrow_robot2flag_->getSceneNode()->setVisible(false);
334  arrow_robot2flag_->setPosition(Ogre::Vector3(0,0,0));
335 
336  }
337 
338  arrow_robot2flag_->set(length - 0.5f, 0.2f, 0.5f, 0.35f);
339  double angle = atan2( intersection.y - arrow_robot2flag_->getPosition().y, intersection.x - arrow_robot2flag_->getPosition().x );
340  Ogre::Quaternion orient_x = Ogre::Quaternion( Ogre::Radian(-Ogre::Math::HALF_PI), Ogre::Vector3::UNIT_Y );
341  arrow_robot2flag_->setOrientation( Ogre::Quaternion( Ogre::Radian(angle), Ogre::Vector3::UNIT_Z ) * orient_x );
342 
343  } else {
344  moving_flag_node_->setVisible(false);
345  }
346  }
347 
348  return Render;
349 }
350 
351 void MultiRobotGoalSelector::makeFlag(const Ogre::Vector3 &position, const Ogre::Quaternion &orientation)
352 {
353  Ogre::SceneNode *node = scene_manager_->getRootSceneNode()->createChildSceneNode();
354  Ogre::Entity *entity = scene_manager_->createEntity(flag_resource_);
355  node->attachObject(entity);
356  node->setVisible(true);
357  node->setPosition(position);
358  node->setOrientation(orientation);
359  TextVisual *tw = new TextVisual(scene_manager_, node, Ogre::Vector3(0,
360  0,
361  node->getAttachedObject(0)->getBoundingBox().getSize().z + 0.15));
362  tw->setCaption(std::to_string(flag_nodes_.size()));
363  tw->setCharacterHeight(0.25);
364  flag_nodes_.push_back(node);
365 
366 }
367 
368 } // namespace tuw_multi_robot_rviz
369 
std::vector< std::unique_ptr< rviz::Arrow > > arrows_robot2flag_
Ogre::SceneManager * scene_manager_
#define NULL
void setCaption(const std::string &caption)
Definition: TextVisual.h:72
void publish(const boost::shared_ptr< M > &message) const
virtual bool setVector(const Ogre::Vector3 &vector)
Ogre::Viewport * viewport
f
virtual int getInt() const
void setMin(int min)
Ogre::MeshPtr loadMeshFromResource(const std::string &resource_path)
char shortcut_key_
void setCharacterHeight(double characterHeight)
Definition: TextVisual.h:63
virtual int processMouseEvent(rviz::ViewportMouseEvent &event)
virtual void removeChildren(int start_index=0, int count=-1)
void make_quaternion(geometry_msgs::Pose::_orientation_type &q, double pitch, double roll, double yaw)
virtual void setReadOnly(bool read_only)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
bool getPointOnPlaneFromWindowXY(Ogre::Viewport *viewport, Ogre::Plane &plane, int window_x, int window_y, Ogre::Vector3 &intersection_out)
virtual Ogre::Vector3 getVector() const
virtual QString getFixedFrame() const =0
DisplayContext * context_
void makeFlag(const Ogre::Vector3 &position, const Ogre::Quaternion &orientation)
std::vector< Ogre::SceneNode * > flag_nodes_
virtual void addChild(Property *child, int index=-1)
static Time now()
virtual Property * getPropertyContainer() const
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
std::vector< rviz::StringProperty * > robot_names_
#define ROS_ERROR(...)


tuw_multi_robot_rviz
Author(s): Benjamin Binder
autogenerated on Mon Jun 10 2019 15:42:40