calibration.cc
Go to the documentation of this file.
00001 
00014 #include <iostream>
00015 #include <fstream>
00016 #include <string>
00017 #include <cmath>
00018 #include <limits>
00019 #include <yaml-cpp/yaml.h>
00020 
00021 #ifdef HAVE_NEW_YAMLCPP
00022 namespace YAML {
00023 
00024   // The >> operator disappeared in yaml-cpp 0.5, so this function is
00025   // added to provide support for code written under the yaml-cpp 0.3 API.
00026   template<typename T>
00027   void operator >> (const YAML::Node& node, T& i) {
00028     i = node.as<T>();
00029   }
00030 } /* YAML */
00031 #endif // HAVE_NEW_YAMLCPP
00032 
00033 #include <ros/ros.h>
00034 #include <velodyne_pointcloud/calibration.h>
00035 
00036 namespace velodyne_pointcloud 
00037 {
00038 
00039   const std::string NUM_LASERS = "num_lasers";
00040   const std::string LASERS = "lasers";
00041   const std::string LASER_ID = "laser_id";
00042   const std::string ROT_CORRECTION = "rot_correction";
00043   const std::string VERT_CORRECTION = "vert_correction";
00044    const std::string DIST_CORRECTION = "dist_correction";
00045   const std::string TWO_PT_CORRECTION_AVAILABLE =
00046     "two_pt_correction_available";
00047   const std::string DIST_CORRECTION_X = "dist_correction_x";
00048   const std::string DIST_CORRECTION_Y = "dist_correction_y";
00049   const std::string VERT_OFFSET_CORRECTION = "vert_offset_correction";
00050   const std::string HORIZ_OFFSET_CORRECTION = "horiz_offset_correction";
00051   const std::string MAX_INTENSITY = "max_intensity";
00052   const std::string MIN_INTENSITY = "min_intensity";
00053   const std::string FOCAL_DISTANCE = "focal_distance";
00054   const std::string FOCAL_SLOPE = "focal_slope";
00055 
00056   void operator >> (const YAML::Node& node,
00057                     std::pair<int, LaserCorrection>& correction)
00058   {
00059     node[LASER_ID] >> correction.first;
00060     node[ROT_CORRECTION] >> correction.second.rot_correction;
00061     node[VERT_CORRECTION] >> correction.second.vert_correction;
00062     node[DIST_CORRECTION] >> correction.second.dist_correction;
00063 #ifdef HAVE_NEW_YAMLCPP
00064     if (node[TWO_PT_CORRECTION_AVAILABLE])
00065       node[TWO_PT_CORRECTION_AVAILABLE] >>
00066         correction.second.two_pt_correction_available;
00067 #else
00068     if (const YAML::Node *pName = node.FindValue(TWO_PT_CORRECTION_AVAILABLE))
00069       *pName >> correction.second.two_pt_correction_available;
00070 #endif
00071     else
00072       correction.second.two_pt_correction_available = false;
00073     node[DIST_CORRECTION_X] >> correction.second.dist_correction_x;
00074     node[DIST_CORRECTION_Y] >> correction.second.dist_correction_y;
00075     node[VERT_OFFSET_CORRECTION] >> correction.second.vert_offset_correction;
00076     node[HORIZ_OFFSET_CORRECTION] >> correction.second.horiz_offset_correction;
00077 #ifdef HAVE_NEW_YAMLCPP
00078     if (node[MAX_INTENSITY])
00079       node[MAX_INTENSITY] >> correction.second.max_intensity;
00080 #else
00081     if (const YAML::Node *pName = node.FindValue(MAX_INTENSITY))
00082       *pName >> correction.second.max_intensity;
00083 #endif
00084     else
00085       correction.second.max_intensity = 255;
00086 #ifdef HAVE_NEW_YAMLCPP
00087     if (node[MIN_INTENSITY])
00088       node[MIN_INTENSITY] >> correction.second.min_intensity;
00089 #else
00090     if (const YAML::Node *pName = node.FindValue(MIN_INTENSITY))
00091       *pName >> correction.second.min_intensity;
00092 #endif
00093     else
00094       correction.second.min_intensity = 0;
00095     node[FOCAL_DISTANCE] >> correction.second.focal_distance;
00096     node[FOCAL_SLOPE] >> correction.second.focal_slope;
00097 
00098     // Calculate cached values
00099     correction.second.cos_rot_correction =
00100       cosf(correction.second.rot_correction);
00101     correction.second.sin_rot_correction =
00102       sinf(correction.second.rot_correction);
00103     correction.second.cos_vert_correction =
00104       cosf(correction.second.vert_correction);
00105     correction.second.sin_vert_correction =
00106       sinf(correction.second.vert_correction);
00107 
00108     correction.second.laser_ring = 0;   // clear initially (set later)
00109   }
00110 
00111   void operator >> (const YAML::Node& node, Calibration& calibration) 
00112   {
00113     int num_lasers;
00114     node[NUM_LASERS] >> num_lasers;
00115     const YAML::Node& lasers = node[LASERS];
00116     calibration.laser_corrections.clear();
00117     calibration.num_lasers = num_lasers;
00118     for (int i = 0; i < num_lasers; i++) {
00119       std::pair<int, LaserCorrection> correction;
00120       lasers[i] >> correction;
00121       calibration.laser_corrections.insert(correction);
00122     }
00123 
00124     // For each laser ring, find the next-smallest vertical angle.
00125     //
00126     // This implementation is simple, but not efficient.  That is OK,
00127     // since it only runs while starting up.
00128     double next_angle = -std::numeric_limits<double>::infinity();
00129     for (int ring = 0; ring < num_lasers; ++ring) {
00130 
00131       // find minimum remaining vertical offset correction
00132       double min_seen = std::numeric_limits<double>::infinity();
00133       int next_index = num_lasers;
00134       for (int j = 0; j < num_lasers; ++j) {
00135 
00136         double angle = calibration.laser_corrections[j].vert_correction;
00137         if (next_angle < angle && angle < min_seen) {
00138           min_seen = angle;
00139           next_index = j;
00140         }
00141       }
00142 
00143       if (next_index < num_lasers) {    // anything found in this ring?
00144 
00145         // store this ring number with its corresponding laser number
00146         calibration.laser_corrections[next_index].laser_ring = ring;
00147         next_angle = min_seen;
00148         ROS_INFO_STREAM("laser_ring[" << next_index << "] = " << ring
00149                          << ", angle = " << next_angle);
00150       }
00151     }
00152   }
00153 
00154   YAML::Emitter& operator << (YAML::Emitter& out,
00155                               const std::pair<int, LaserCorrection> correction)
00156   {
00157     out << YAML::BeginMap;
00158     out << YAML::Key << LASER_ID << YAML::Value << correction.first;
00159     out << YAML::Key << ROT_CORRECTION <<
00160       YAML::Value << correction.second.rot_correction;
00161     out << YAML::Key << VERT_CORRECTION <<
00162       YAML::Value << correction.second.vert_correction;
00163     out << YAML::Key << DIST_CORRECTION <<
00164       YAML::Value << correction.second.dist_correction;
00165     out << YAML::Key << TWO_PT_CORRECTION_AVAILABLE <<
00166       YAML::Value << correction.second.two_pt_correction_available;
00167     out << YAML::Key << DIST_CORRECTION_X <<
00168       YAML::Value << correction.second.dist_correction_x;
00169     out << YAML::Key << DIST_CORRECTION_Y <<
00170       YAML::Value << correction.second.dist_correction_y;
00171     out << YAML::Key << VERT_OFFSET_CORRECTION <<
00172       YAML::Value << correction.second.vert_offset_correction;
00173     out << YAML::Key << HORIZ_OFFSET_CORRECTION <<
00174       YAML::Value << correction.second.horiz_offset_correction;
00175     out << YAML::Key << MAX_INTENSITY <<
00176       YAML::Value << correction.second.max_intensity;
00177     out << YAML::Key << MIN_INTENSITY <<
00178       YAML::Value << correction.second.min_intensity;
00179     out << YAML::Key << FOCAL_DISTANCE <<
00180       YAML::Value << correction.second.focal_distance;
00181     out << YAML::Key << FOCAL_SLOPE <<
00182       YAML::Value << correction.second.focal_slope;
00183     out << YAML::EndMap;
00184     return out;
00185   }
00186 
00187   YAML::Emitter& operator <<
00188   (YAML::Emitter& out, const Calibration& calibration)
00189   {
00190     out << YAML::BeginMap;
00191     out << YAML::Key << NUM_LASERS <<
00192       YAML::Value << calibration.laser_corrections.size();
00193     out << YAML::Key << LASERS << YAML::Value << YAML::BeginSeq;
00194     for (std::map<int, LaserCorrection>::const_iterator
00195            it = calibration.laser_corrections.begin();
00196          it != calibration.laser_corrections.end(); it++)
00197       {
00198         out << *it; 
00199       }
00200     out << YAML::EndSeq;
00201     out << YAML::EndMap;
00202     return out;
00203   }
00204 
00205   void Calibration::read(const std::string& calibration_file) {
00206     std::ifstream fin(calibration_file.c_str());
00207     if (!fin.is_open()) {
00208       initialized = false;
00209       return;
00210     }
00211     initialized = true;
00212     try {
00213       YAML::Node doc;
00214 #ifdef HAVE_NEW_YAMLCPP
00215       fin.close();
00216       doc = YAML::LoadFile(calibration_file);
00217 #else
00218       YAML::Parser parser(fin);
00219       parser.GetNextDocument(doc);
00220 #endif
00221       doc >> *this;
00222     } catch (YAML::Exception &e) {
00223       std::cerr << "YAML Exception: " << e.what() << std::endl;
00224       initialized = false;
00225     }
00226     fin.close();
00227   }
00228 
00229   void Calibration::write(const std::string& calibration_file) {
00230     std::ofstream fout(calibration_file.c_str());
00231     YAML::Emitter out;
00232     out << *this;
00233     fout << out.c_str();
00234     fout.close();
00235   }
00236   
00237 } /* velodyne_pointcloud */


velodyne_pointcloud
Author(s): Jack O'Quin, Piyush Khandelwal, Jesse Vera
autogenerated on Thu Aug 27 2015 15:37:05