OctomapInterface.cpp
Go to the documentation of this file.
1 
3 // OctomapSensorSystem.cpp
4 //
5 // Created on: Jan 24, 2014
6 // Author: mklingen
8 
9 #include "OctomapInterface.h"
11 #include <std_srvs/EmptyRequest.h>
12 #include <std_srvs/EmptyResponse.h>
13 #include <boost/thread.hpp>
14 #include <boost/thread/mutex.hpp>
15 #include <octomap_server/OctomapServer.h>
16 using namespace OpenRAVE;
17 using namespace octomap_server;
18 
19 #define SAFE_DELETE(x) if((x)) { delete (x); x = NULL; }
20 bool is_equal (double a, double b, double epsilon = 1.0e-7)
21 {
22  return std::abs(a - b) < epsilon;
23 }
24 
25 namespace or_octomap
26 {
27  OctomapInterface::OctomapInterface(ros::NodeHandle& nodeHandle, OpenRAVE::EnvironmentBasePtr env):
28  SensorSystemBase(env), OctomapServer(nodeHandle), m_shouldExit(false)
29  {
30  m_isPaused = false;
31  m_pointCloudSub->unsubscribe();
32 
33  delete m_tfPointCloudSub;
34 
35  m_pointCloudSub = new message_filters::Subscriber<sensor_msgs::PointCloud2> (m_nh, "/cloud_in", 1, ros::TransportHints(), &m_queue);
36  m_tfPointCloudSub = new tf::MessageFilter<sensor_msgs::PointCloud2> (*m_pointCloudSub, m_tfListener, m_worldFrameId, 1, m_nh, ros::Duration(0.01));
37  m_tfPointCloudSub->registerCallback(boost::bind(&OctomapInterface::InsertCloudWrapper, this, _1));
38 
39  ROS_INFO("Frame ID: %s", m_worldFrameId.c_str());
40  ROS_INFO("Topic: %s", m_pointCloudSub->getTopic().c_str());
41 
42  RegisterCommand("Enable", boost::bind(&OctomapInterface::Enable, this, _1, _2),
43  "Begin collision testing octomap");
44  RegisterCommand("Disable", boost::bind(&OctomapInterface::Disable, this, _1, _2),
45  "Stop collision testing octomap.");
46  RegisterCommand("Mask", boost::bind(&OctomapInterface::MaskObject, this, _1, _2),
47  "Mask an object out of the octomap");
48  RegisterCommand("TogglePause", boost::bind(&OctomapInterface::TogglePause, this, _1, _2),
49  "Toggles the octomap to being paused/unpaused for collecting data");
50  RegisterCommand("Save", boost::bind(&OctomapInterface::SaveTree, this, _1, _2),
51  "Save the OcTree to a file.");
52  RegisterCommand("Reset", boost::bind(&OctomapInterface::ResetTree, this, _1, _2),
53  "Reset the octomap.");
54  RegisterCommand("ResetTopic", boost::bind(&OctomapInterface::ResetTopic, this, _1, _2),
55  "Reset the point cloud topic.");
56  RegisterCommand("ResetResolution", boost::bind(&OctomapInterface::ResetResolution, this, _1, _2),
57  "Reset the octomap resolution.");
58  RegisterCommand("ResetFrameID", boost::bind(&OctomapInterface::ResetFrame, this, _1, _2),
59  "Reset the octomap frame_id.");
60 
61  m_collisionChecker = NULL;
62  boost::thread spinThread = boost::thread(boost::bind(&OctomapInterface::Spin, this));
63  m_reconfigureServer.clearCallback();
64  }
65 
67  octomap_server::OctomapServerConfig config;
68  int max_tree_depth;
69  ros::param::get("or_octomap/max_depth", max_tree_depth);
70  m_maxTreeDepth = unsigned(max_tree_depth);
71  ros::param::get("or_octomap/pointcloud_min_z", m_pointcloudMinZ);
72  ros::param::get("or_octomap/pointcloud_max_z", m_pointcloudMaxZ);
73  ros::param::get("or_octomap/occupancy_min_z", m_occupancyMinZ);
74  ros::param::get("or_octomap/occupancy_max_z", m_occupancyMaxZ);
75  ros::param::get("or_octomap/filter_speckles", m_filterSpeckles);
76  ros::param::get("or_octomap/filter_ground", m_filterGroundPlane);
77  ros::param::get("or_octomap/compress_map", m_compressMap);
78  ros::param::get("or_octomap/incremental_2D_projection", m_incrementalUpdate);
79  ros::param::get("or_octomap/ground_filter_distance", m_groundFilterDistance);
80  ros::param::get("or_octomap/ground_filter_angle", m_groundFilterAngle);
81  ros::param::get("or_octomap/ground_filter_plane_distance", m_groundFilterPlaneDistance);
82  ros::param::get("or_octomap/sensor_model_max_range", m_maxRange);
83 
84  double sensor_model_min;
85  double sensor_model_max;
86  double sensor_model_hit;
87  double sensor_model_miss;
88  ros::param::get("or_octomap/sensor_model_min", sensor_model_min);
89  ros::param::get("or_octomap/sensor_model_max", sensor_model_max);
90  ros::param::get("or_octomap/sensor_model_hit", sensor_model_hit);
91  ros::param::get("or_octomap/sensor_model_miss", sensor_model_miss);
92  m_octree->setClampingThresMin(sensor_model_min);
93  m_octree->setClampingThresMax(sensor_model_max);
94 
95  if (is_equal(sensor_model_hit, 1.0)) sensor_model_hit -= 1.0e-6;
96  m_octree->setProbHit(sensor_model_hit);
97  if (is_equal(sensor_model_miss, 0.0)) sensor_model_miss += 1.0e-6;
98  m_octree->setProbMiss(sensor_model_miss);
99  config.max_depth = max_tree_depth;
100  config.pointcloud_min_z = m_pointcloudMinZ;
101  config.pointcloud_max_z = m_pointcloudMaxZ;
102  config.occupancy_min_z = m_occupancyMinZ;
103  config.occupancy_max_z = m_occupancyMaxZ;
104  config.filter_speckles = m_filterSpeckles;
105  config.filter_ground = m_filterGroundPlane;
106  config.compress_map = m_compressMap;
107  config.incremental_2D_projection = m_incrementalUpdate;
108  config.ground_filter_distance = m_groundFilterDistance;
109  config.ground_filter_angle = m_groundFilterAngle;
110  config.ground_filter_plane_distance = m_groundFilterPlaneDistance;
111  config.sensor_model_max_range = m_maxRange;
112  config.sensor_model_min = sensor_model_min;
113  config.sensor_model_max = sensor_model_max;
114  config.sensor_model_hit = sensor_model_hit;
115  config.sensor_model_miss = sensor_model_miss;
116 
117  boost::recursive_mutex::scoped_lock reconf_lock(m_config_mutex);
118  m_reconfigureServer.updateConfig(config);
119  reconf_lock.unlock();
120  }
121 
122  void OctomapInterface::InsertCloudWrapper(const sensor_msgs::PointCloud2::ConstPtr& cloud)
123  {
124  boost::mutex::scoped_lock(m_cloudQueueMutex);
125 
126  if(!m_isPaused)
127  {
128  m_cloudQueue.push_back(cloud);
129  }
130  }
131 
133  {
134  while(m_cloudQueue.size() > 0)
135  {
136  boost::mutex::scoped_lock(m_cloudQueueMutex);
137 
138  insertCloudCallback(m_cloudQueue.front());
139  m_cloudQueue.erase(m_cloudQueue.begin());
140  }
141  }
142 
144  {
145  float timey = 0.0f;
146  bool lastCollisionState = false;
147  while(!m_shouldExit)
148  {
149  timey += 0.01f;
150  OpenRAVE::CollisionReportPtr report(new OpenRAVE::CollisionReport());
151  OpenRAVE::KinBodyConstPtr fakeBody = GetEnv()->GetKinBody("_OCTOMAP_MAP_");
152  OpenRAVE::KinBodyPtr fuze = GetEnv()->GetKinBody("fuze_bottle");
153  if(fakeBody.get())
154  {
155  boost::mutex::scoped_lock(m_cloudQueueMutex);
156  bool collides = GetEnv()->CheckCollision(fakeBody, report);
157 
158  ROS_INFO("Collides: %s", collides ? "true" : "false");
159 
160  OpenRAVE::Transform t;
161  t.identity();
162 
163  float r = 0.1 * cos(timey * 0.1f);
164  t.trans = OpenRAVE::Vector(r * sin(timey) + 0.5f, r * cos(timey), 0.0f);
165 
166  if(fuze.get())
167  {
168  fuze->SetTransform(t);
169  }
170  lastCollisionState = collides;
171  }
172  usleep(10000);
173  }
174  }
175 
177  {
178  ros::WallDuration timeout(0.01);
179  while(!m_shouldExit)
180  {
181  if(!m_isPaused){updateParam();}
182  m_queue.callOne(timeout);
183  InsertScans();
184  }
185  }
186 
188  {
189  SetEnabled(false);
190  m_shouldExit = true;
191  }
192 
193  void OctomapInterface::SetEnabled(bool enabled)
194  {
195  ROS_DEBUG("Set enabled called!");
196  m_isEnabled = enabled;
197 
198  if(enabled)
199  {
201  {
202  GetEnv()->SetCollisionChecker(m_collisionChecker->GetWrappedChecker());
204  }
205 
206  OpenRAVE::CollisionCheckerBasePtr collisionCheckerBase = RaveCreateCollisionChecker(GetEnv(), "or_octomap_checker");
207 
208  m_collisionChecker = dynamic_cast<OctomapCollisionChecker*>(collisionCheckerBase.get());
209  //new OctomapCollisionChecker(GetEnv(), GetEnv()->GetCollisionChecker(), this);
211  m_collisionChecker->SetWrappedChecker(GetEnv()->GetCollisionChecker());
212  CreateFakeBody();
213  GetEnv()->SetCollisionChecker(collisionCheckerBase);
214  }
215  else
216  {
218  {
219  GetEnv()->SetCollisionChecker(m_collisionChecker->GetWrappedChecker());
221  DestroyFakeBody();
222  }
223  }
224  }
225 
227  {
228  OpenRAVE::KinBodyPtr kinBody = GetEnv()->GetKinBody("_OCTOMAP_MAP_");
229 
230  if(kinBody.get())
231  {
232  GetEnv()->Remove(kinBody);
233  }
234  }
235 
237  {
238  ROS_DEBUG("Creating fake body!");
239  OpenRAVE::KinBodyPtr kinbody = RaveCreateKinBody(GetEnv(), "");
240  kinbody->SetName("_OCTOMAP_MAP_");
241  GetEnv()->Add(kinbody);
242  }
243 
244  bool OctomapInterface::SendCommand(std::ostream &os, std::istream &is)
245  {
246  return SensorSystemBase::SendCommand(os, is);
247  }
248 
250  {
251  std_srvs::EmptyRequest req;
252  std_srvs::EmptyResponse res;
253  resetSrv(req, res);
254  }
255 
256  bool OctomapInterface::ResetTree(std::ostream &os, std::istream &i)
257  {
258  ROS_DEBUG("Reset the octomap.");
259  if(!m_isPaused)
260  {
262  }
263  ros::Duration(0.1).sleep();
264  std_srvs::EmptyRequest req;
265  std_srvs::EmptyResponse res;
266  resetSrv(req, res);
267  if(m_isPaused)
268  {
270  }
271  return true;
272  }
273 
274  bool OctomapInterface::ResetResolution(std::ostream &os, std::istream &i){
275  std::string strRes;
276  i >> strRes;
277  ROS_INFO("Reset resolution as %f", std::atof(strRes.c_str()));
278  double resolution = std::atof(strRes.c_str());
279 
280  if(!m_isPaused)
281  {
283  }
284  ros::Duration(0.1).sleep();
285  m_res = resolution;
286  m_octree->setResolution(resolution);
287  std_srvs::EmptyRequest req;
288  std_srvs::EmptyResponse res;
289  resetSrv(req, res);
290  if(m_isPaused)
291  {
293  }
294  return true;
295  }
296 
297  bool OctomapInterface::ResetFrame(std::ostream &os, std::istream &i){
298  std::string frameID;
299  i >> frameID;
300  ROS_INFO("Reset frame_id as %s", frameID.c_str());
301 
302  if(!m_isPaused)
303  {
305  }
306  ros::Duration(0.1).sleep();
307  if(frameID == "" || !IsEnabled())
308  {
309  return false;
310  }
311 
312  m_worldFrameId = frameID;
313  delete m_tfPointCloudSub;
314 
315  m_tfPointCloudSub = new tf::MessageFilter<sensor_msgs::PointCloud2> (*m_pointCloudSub, m_tfListener, m_worldFrameId, 1, m_nh, ros::Duration(0.1));
316  m_tfPointCloudSub->registerCallback(boost::bind(&OctomapInterface::InsertCloudWrapper, this, _1));
317 
318  std_srvs::EmptyRequest req;
319  std_srvs::EmptyResponse res;
320  resetSrv(req, res);
321  if(m_isPaused)
322  {
324  }
325  return true;
326  }
327 
328  bool OctomapInterface::MaskObject(std::ostream &os, std::istream &i)
329  {
330  std::string objectName;
331  i >> objectName;
332 
333  ROS_DEBUG("Masking object %s", objectName.c_str());
334 
335  if(objectName == "" || !IsEnabled())
336  {
337  return false;
338  }
339  bool toReturn = m_collisionChecker->MaskObject(objectName);
340  publishAll();
341  return toReturn;
342  }
343 
344  bool OctomapInterface::SaveTree(std::ostream &os, std::istream &i){
345 
346  std::string file_name;
347  i >> file_name;
348 
349  ROS_DEBUG("Saving the tree to the file: %s", file_name.c_str());
350 
351  if(file_name == "" || !IsEnabled())
352  {
353  return false;
354  }
355 
356  std::size_t octomapSize = m_octree->size();
357  // TODO: estimate num occ. voxels for size of arrays (reserve)
358  if (octomapSize <= 1){
359  ROS_WARN("The octree is empty, could not save the octomap to the file %s.", file_name.c_str());
360  return false;
361  }
362 
363  std::string vrmlFilename = "";
364  vrmlFilename = file_name + ".wrl";
365 
366  std::ofstream outfile (vrmlFilename.c_str());
367  outfile << "#VRML V2.0 utf8\n#\n";
368  outfile << "# created from OctoMap \n";
369 
370  octomap::OcTree* tree = GetTree();
371 
372  std::size_t count(0);
373  for(octomap::OcTree::iterator it = tree->begin(m_maxTreeDepth), end=tree->end(); it!= end; ++it) {
374  if(tree->isNodeOccupied(*it)){
375  count++;
376  double size = it.getSize();
377  double x = it.getX();
378  double y = it.getY();
379  double z = it.getZ();
380 
381  geometry_msgs::Point cubeCenter;
382  cubeCenter.x = x;
383  cubeCenter.y = y;
384  cubeCenter.z = z;
385 
386  double minX, minY, minZ, maxX, maxY, maxZ;
387  m_octree->getMetricMin(minX, minY, minZ);
388  m_octree->getMetricMax(maxX, maxY, maxZ);
389  double h = (1.0 - std::min(std::max((cubeCenter.z-minZ)/ (maxZ - minZ), 0.0), 1.0)) *m_colorFactor;
390  std_msgs::ColorRGBA _color = heightMapColor(h);
391 
392  outfile << "Transform { translation "
393  << it.getX() << " " << it.getY() << " " << it.getZ()
394  << " \n children [ Shape { "
395  << "appearance Appearance { material Material { diffuseColor "
396  << _color.r << " "<< _color.g << " " << _color.b << " } } "
397  << "geometry Box { size " << size << " " << size << " " << size << " }"
398  << " } ]\n}\n";
399  }
400  }
401  outfile.close();
402  std::cout << "Finished writing "<< count << " voxels to " << vrmlFilename << std::endl;
403  return true;
404  }
405 
406  bool OctomapInterface::ResetTopic(std::ostream &os, std::istream &i){
407 
408  std::string topic_name;
409  i >> topic_name;
410 
411  ROS_INFO("Reset the point cloud topic as: %s",topic_name.c_str());
412 
413  if(topic_name == "" || !IsEnabled())
414  {
415  return false;
416  }
417 
418  m_pointCloudSub->unsubscribe();
419 
420  //delete m_pointCloudSub;
421  delete m_tfPointCloudSub;
422 
423  m_pointCloudSub = new message_filters::Subscriber<sensor_msgs::PointCloud2> (m_nh, topic_name, 1, ros::TransportHints(), &m_queue);
424  m_tfPointCloudSub = new tf::MessageFilter<sensor_msgs::PointCloud2> (*m_pointCloudSub, m_tfListener, m_worldFrameId, 1, m_nh, ros::Duration(0.1));
425  m_tfPointCloudSub->registerCallback(boost::bind(&OctomapInterface::InsertCloudWrapper, this, _1));
426 
427  ROS_DEBUG("Topic: %s", m_pointCloudSub->getTopic().c_str());
428  }
429 }
void SetWrappedChecker(OpenRAVE::CollisionCheckerBasePtr checker)
bool MaskObject(std::ostream &os, std::istream &i)
float max(float a, float b, float c)
bool TogglePause(std::ostream &os, std::istream &i)
bool Disable(std::ostream &os, std::istream &i)
void SetInterface(OctomapInterface *interface)
bool ResetTopic(std::ostream &os, std::istream &i)
octomap::OcTree * GetTree()
bool Enable(std::ostream &os, std::istream &i)
std::vector< sensor_msgs::PointCloud2ConstPtr > m_cloudQueue
bool ResetTree(std::ostream &os, std::istream &i)
float min(float a, float b, float c)
OctomapCollisionChecker * m_collisionChecker
void InsertCloudWrapper(const sensor_msgs::PointCloud2::ConstPtr &cloud)
bool is_equal(double a, double b, double epsilon=1.0e-7)
#define SAFE_DELETE(x)
bool SaveTree(std::ostream &os, std::istream &i)
bool ResetFrame(std::ostream &os, std::istream &i)
bool ResetResolution(std::ostream &os, std::istream &i)
OpenRAVE::CollisionCheckerBasePtr GetWrappedChecker()
virtual bool SendCommand(std::ostream &os, std::istream &is)


or_octomap_plugin
Author(s): Yan Yu
autogenerated on Tue Oct 24 2017 18:02:48