Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <ros/ros.h>
00038
00039 #include <pcl_conversions/pcl_conversions.h>
00040
00041 #include <sensor_msgs/PointCloud2.h>
00042 #include <sick_ldmrs_msgs/sick_ldmrs_point_type.h>
00043 #include <pcl/point_cloud.h>
00044
00045 typedef std::vector<std::pair<double, double> > ResolutionMap;
00046 typedef sick_ldmrs_msgs::SICK_LDMRS_Point PointT;
00047 typedef pcl::PointCloud<PointT> PointCloudT;
00048
00049 #ifndef deg2rad
00050 #define deg2rad 0.01745329251994329576923690768 // (PI / 180.0)
00051 #endif
00052 #ifndef rad2deg
00053 #define rad2deg 57.29577951308232087679815481 // (180.0 / PI)
00054 #endif
00055
00056 std::string doubleToString(double val,
00057 int digits_after_decimal_point)
00058 {
00059 std::ostringstream ss;
00060 ss << std::fixed << std::setprecision(digits_after_decimal_point) << val;
00061
00062 return ss.str();
00063 }
00064
00065 inline bool almostEqual(double a, double b)
00066 {
00067 return std::abs(a - b) < 1e-6f;
00068 }
00069
00070 inline double getHAngle(const PointT &p)
00071 {
00072 return atan2(p.y, p.x);
00073 }
00074
00075 std::string sectorToString(const ResolutionMap& sector)
00076 {
00077 size_t i = 0;
00078 std::ostringstream oss;
00079 oss << std::endl;
00080 for (ResolutionMap::const_iterator s = sector.begin(); s != sector.end(); ++s)
00081 {
00082 oss << "Sector (" << i << "): start=" << doubleToString(s->first * rad2deg, 3) << " (= " << (int)(round(s->first * rad2deg * 32.0)) << ") res=" << doubleToString(s->second * rad2deg, 3) << std::endl;
00083 i++;
00084 }
00085
00086 return oss.str();
00087 }
00088
00089 PointCloudT::const_iterator getNextPointInSameLayer(PointCloudT::const_iterator iter, const PointCloudT::ConstPtr cloud)
00090 {
00091 PointCloudT::const_iterator ret = iter;
00092 for (++iter ; iter != cloud->end(); ++iter)
00093 {
00094 if (iter->layer == ret->layer)
00095 {
00096 ret = iter;
00097 break;
00098 }
00099 }
00100 return ret;
00101
00102 }
00103
00104 PointCloudT::const_iterator getNextPoint(PointCloudT::const_iterator iter, const PointCloudT::ConstPtr cloud)
00105 {
00106 PointCloudT::const_iterator ret = iter;
00107 ++iter;
00108 if (iter != cloud->end())
00109 {
00110 ret = iter;
00111 }
00112 return ret;
00113
00114 }
00115
00116 void checkResolution(const PointCloudT::ConstPtr cloud)
00117 {
00118 if (cloud->size() < 10)
00119 {
00120
00121 return;
00122 }
00123
00124
00125 PointCloudT::const_iterator p;
00126 double angleDiff;
00127
00128 ResolutionMap sectors;
00129
00130 for (p = cloud->begin(); p != cloud->end(); ++p)
00131 {
00132 PointCloudT::const_iterator p2 = getNextPoint(p, cloud);
00133 PointCloudT::const_iterator p3 = getNextPointInSameLayer(p, cloud);
00134 double interlaced = 1.;
00135 if (almostEqual(getHAngle(*p2), getHAngle(*p3)))
00136 {
00137
00138 interlaced = 0.5;
00139
00140 }
00141 angleDiff = std::fabs(getHAngle(*p2) - getHAngle(*p)) * interlaced;
00142
00143 if (angleDiff > 1e-6f)
00144 {
00145 if (almostEqual(angleDiff, 0.125 * deg2rad)
00146 || almostEqual(angleDiff, 0.25 * deg2rad)
00147 || almostEqual(angleDiff, 0.5 * deg2rad)
00148 || almostEqual(angleDiff, 1.0 * deg2rad))
00149 {
00150 if (sectors.size() == 0)
00151 {
00152 sectors.push_back(std::make_pair(getHAngle(*p), angleDiff));
00153 }
00154 else
00155 {
00156
00157 if (almostEqual(double(sectors.back().second), angleDiff) == false)
00158 {
00159 sectors.push_back(std::make_pair(getHAngle(*p), angleDiff));
00160 }
00161 }
00162 }
00163 }
00164 }
00165
00166
00167 ResolutionMap sectors_filtered;
00168 bool changed = true;
00169 while (changed)
00170 {
00171 changed = false;
00172 for (size_t i = 0; i < sectors.size() - 1; ++i)
00173 {
00174 if (sectors[i].first - sectors[i + 1].first > (3.0 + 1e-6f) * deg2rad &&
00175 !almostEqual(sectors[i].second, sectors[i + 1].second))
00176 {
00177 sectors_filtered.push_back(sectors[i]);
00178 }
00179 else
00180 {
00181 sectors[i + 1].first = sectors[i].first;
00182 changed = true;
00183 }
00184 }
00185 sectors_filtered.push_back(sectors.back());
00186 sectors.swap(sectors_filtered);
00187 sectors_filtered.clear();
00188 }
00189
00190 std::ostringstream oss;
00191 oss << "Angular resolutions:" << sectorToString(sectors);
00192 ROS_INFO("%s", oss.str().c_str());
00193 }
00194
00195 void callback(const sensor_msgs::PointCloud2::ConstPtr& pc)
00196 {
00197
00198 PointCloudT::Ptr cloud = boost::make_shared<PointCloudT>();
00199 pcl::fromROSMsg(*pc, *cloud);
00200
00201 checkResolution(cloud);
00202 }
00203
00204 int main(int argc, char **argv)
00205 {
00206 ros::init(argc, argv, "sick_ldmrs_print_resolution");
00207 ros::NodeHandle nh;
00208
00209 ros::Subscriber sub = nh.subscribe("cloud", 1, callback);
00210
00211 ros::spin();
00212
00213 return 0;
00214 }