sick_ldmrs_print_resolution.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2016, DFKI GmbH
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 DFKI GmbH 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  * Authors:
30  * Martin Günther <martin.guenther@dfki.de>
31  * Jochen Sprickerhof <ros@jochen.sprickerhof.de>
32  *
33  * Based on LD-MRS example code by SICK AG.
34  *
35  */
36 
37 #include <ros/ros.h>
38 
40 
41 #include <sensor_msgs/PointCloud2.h>
43 #include <pcl/point_cloud.h>
44 
45 typedef std::vector<std::pair<double, double> > ResolutionMap;
47 typedef pcl::PointCloud<PointT> PointCloudT;
48 
49 #ifndef deg2rad
50 #define deg2rad 0.01745329251994329576923690768 // (PI / 180.0)
51 #endif
52 #ifndef rad2deg
53 #define rad2deg 57.29577951308232087679815481 // (180.0 / PI)
54 #endif
55 
56 std::string doubleToString(double val,
57  int digits_after_decimal_point)
58 {
59  std::ostringstream ss;
60  ss << std::fixed << std::setprecision(digits_after_decimal_point) << val;
61 
62  return ss.str();
63 }
64 
65 inline bool almostEqual(double a, double b)
66 {
67  return std::abs(a - b) < 1e-6f;
68 }
69 
70 inline double getHAngle(const PointT &p)
71 {
72  return atan2(p.y, p.x);
73 }
74 
75 std::string sectorToString(const ResolutionMap& sector)
76 {
77  size_t i = 0;
78  std::ostringstream oss;
79  oss << std::endl;
80  for (ResolutionMap::const_iterator s = sector.begin(); s != sector.end(); ++s)
81  {
82  oss << "Sector (" << i << "): start=" << doubleToString(s->first * rad2deg, 3) << " (= " << (int)(round(s->first * rad2deg * 32.0)) << ") res=" << doubleToString(s->second * rad2deg, 3) << std::endl;
83  i++;
84  }
85 
86  return oss.str();
87 }
88 
89 PointCloudT::const_iterator getNextPointInSameLayer(PointCloudT::const_iterator iter, const PointCloudT::ConstPtr cloud)
90 {
91  PointCloudT::const_iterator ret = iter;
92  for (++iter /*start with the next point*/ ; iter != cloud->end(); ++iter)
93  {
94  if (iter->layer == ret->layer)
95  {
96  ret = iter;
97  break;
98  }
99  }
100  return ret;
101 
102 }
103 
104 PointCloudT::const_iterator getNextPoint(PointCloudT::const_iterator iter, const PointCloudT::ConstPtr cloud)
105 {
106  PointCloudT::const_iterator ret = iter;
107  ++iter;
108  if (iter != cloud->end())
109  {
110  ret = iter;
111  }
112  return ret;
113 
114 }
115 
116 void checkResolution(const PointCloudT::ConstPtr cloud)
117 {
118  if (cloud->size() < 10)
119  {
120  // do not process on scans with too few scan points
121  return;
122  }
123 
124  // iterate through all scan points and make a diff of the angles
125  PointCloudT::const_iterator p;
126  double angleDiff; // compute differences
127 
128  ResolutionMap sectors; // first = start angle, second = resolution
129 
130  for (p = cloud->begin(); p != cloud->end(); ++p)
131  {
132  PointCloudT::const_iterator p2 = getNextPoint(p, cloud);
133  PointCloudT::const_iterator p3 = getNextPointInSameLayer(p, cloud);
134  double interlaced = 1.;
135  if (almostEqual(getHAngle(*p2), getHAngle(*p3)))
136  {
137  // we are close to the border -> only 2 scan layers left
138  interlaced = 0.5;
139 
140  }
141  angleDiff = std::fabs(getHAngle(*p2) - getHAngle(*p)) * interlaced;
142 
143  if (angleDiff > 1e-6f)
144  {
145  if (almostEqual(angleDiff, 0.125 * deg2rad)
146  || almostEqual(angleDiff, 0.25 * deg2rad)
147  || almostEqual(angleDiff, 0.5 * deg2rad)
148  || almostEqual(angleDiff, 1.0 * deg2rad))
149  {
150  if (sectors.size() == 0)
151  {
152  sectors.push_back(std::make_pair(getHAngle(*p), angleDiff));
153  }
154  else
155  {
156  // we detected a new resolution
157  if (almostEqual(double(sectors.back().second), angleDiff) == false)
158  {
159  sectors.push_back(std::make_pair(getHAngle(*p), angleDiff));
160  }
161  }
162  }
163  }
164  }
165 
166  // filter out sectors < 3° or with same resolution as next sector
167  ResolutionMap sectors_filtered;
168  bool changed = true;
169  while (changed)
170  {
171  changed = false;
172  for (size_t i = 0; i < sectors.size() - 1; ++i)
173  {
174  if (sectors[i].first - sectors[i + 1].first > (3.0 + 1e-6f) * deg2rad &&
175  !almostEqual(sectors[i].second, sectors[i + 1].second))
176  {
177  sectors_filtered.push_back(sectors[i]);
178  }
179  else
180  {
181  sectors[i + 1].first = sectors[i].first;
182  changed = true;
183  }
184  }
185  sectors_filtered.push_back(sectors.back());
186  sectors.swap(sectors_filtered);
187  sectors_filtered.clear();
188  }
189 
190  std::ostringstream oss;
191  oss << "Angular resolutions:" << sectorToString(sectors);
192  ROS_INFO("%s", oss.str().c_str());
193 }
194 
195 void callback(const sensor_msgs::PointCloud2::ConstPtr& pc)
196 {
197 
198  PointCloudT::Ptr cloud = boost::make_shared<PointCloudT>();
199  pcl::fromROSMsg(*pc, *cloud);
200 
201  checkResolution(cloud);
202 }
203 
204 int main(int argc, char **argv)
205 {
206  ros::init(argc, argv, "sick_ldmrs_print_resolution");
207  ros::NodeHandle nh;
208 
209  ros::Subscriber sub = nh.subscribe("cloud", 1, callback);
210 
211  ros::spin();
212 
213  return 0;
214 }
int main(int argc, char **argv)
f
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
XmlRpcServer s
void callback(const sensor_msgs::PointCloud2::ConstPtr &pc)
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
void fromROSMsg(const sensor_msgs::PointCloud2 &cloud, pcl::PointCloud< T > &pcl_cloud)
ROSCPP_DECL void spin(Spinner &spinner)
#define ROS_INFO(...)
PointCloudT::const_iterator getNextPoint(PointCloudT::const_iterator iter, const PointCloudT::ConstPtr cloud)
double getHAngle(const PointT &p)
std::string doubleToString(double val, int digits_after_decimal_point)
void checkResolution(const PointCloudT::ConstPtr cloud)
bool almostEqual(double a, double b)
std::vector< std::pair< double, double > > ResolutionMap
std::string sectorToString(const ResolutionMap &sector)
INLINE Rall1d< T, V, S > atan2(const Rall1d< T, V, S > &y, const Rall1d< T, V, S > &x)
sick_ldmrs_msgs::SICK_LDMRS_Point PointT
PointCloudT::const_iterator getNextPointInSameLayer(PointCloudT::const_iterator iter, const PointCloudT::ConstPtr cloud)
pcl::PointCloud< PointT > PointCloudT


sick_ldmrs_tools
Author(s): Martin Günther , Jochen Sprickerhof
autogenerated on Sun Oct 25 2020 03:33:58