123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- /**
- * \file calibration.cc
- * \brief
- *
- * \author Piyush Khandelwal (piyushk@cs.utexas.edu)
- * Copyright (C) 2012, Austin Robot Technology,
- * The University of Texas at Austin
- *
- * License: Modified BSD License
- *
- * $ Id: 02/14/2012 11:36:36 AM piyushk $
- */
- #include <iostream>
- #include <fstream>
- #include <string>
- #include <cmath>
- #include <limits>
- #include <yaml-cpp/yaml.h>
- #ifdef HAVE_NEW_YAMLCPP
- namespace YAML {
- // The >> operator disappeared in yaml-cpp 0.5, so this function is
- // added to provide support for code written under the yaml-cpp 0.3 API.
- template<typename T>
- void operator >> (const YAML::Node& node, T& i) {
- i = node.as<T>();
- }
- } /* YAML */
- #endif // HAVE_NEW_YAMLCPP
- #include "calibration.h"
- namespace velodyne_pointcloud
- {
- const std::string NUM_LASERS = "num_lasers";
- const std::string DISTANCE_RESOLUTION = "distance_resolution";
- const std::string LASERS = "lasers";
- const std::string LASER_ID = "laser_id";
- const std::string ROT_CORRECTION = "rot_correction";
- const std::string VERT_CORRECTION = "vert_correction";
- const std::string DIST_CORRECTION = "dist_correction";
- const std::string TWO_PT_CORRECTION_AVAILABLE =
- "two_pt_correction_available";
- const std::string DIST_CORRECTION_X = "dist_correction_x";
- const std::string DIST_CORRECTION_Y = "dist_correction_y";
- const std::string VERT_OFFSET_CORRECTION = "vert_offset_correction";
- const std::string HORIZ_OFFSET_CORRECTION = "horiz_offset_correction";
- const std::string MAX_INTENSITY = "max_intensity";
- const std::string MIN_INTENSITY = "min_intensity";
- const std::string FOCAL_DISTANCE = "focal_distance";
- const std::string FOCAL_SLOPE = "focal_slope";
- /** Read calibration for a single laser. */
- void operator >> (const YAML::Node& node,
- std::pair<int, LaserCorrection>& correction)
- {
- node[LASER_ID] >> correction.first;
- node[ROT_CORRECTION] >> correction.second.rot_correction;
- node[VERT_CORRECTION] >> correction.second.vert_correction;
- node[DIST_CORRECTION] >> correction.second.dist_correction;
- #ifdef HAVE_NEW_YAMLCPP
- if (node[TWO_PT_CORRECTION_AVAILABLE])
- node[TWO_PT_CORRECTION_AVAILABLE] >>
- correction.second.two_pt_correction_available;
- #else
- if (const YAML::Node *pName = node.FindValue(TWO_PT_CORRECTION_AVAILABLE))
- *pName >> correction.second.two_pt_correction_available;
- #endif
- else
- correction.second.two_pt_correction_available = false;
- node[DIST_CORRECTION_X] >> correction.second.dist_correction_x;
- node[DIST_CORRECTION_Y] >> correction.second.dist_correction_y;
- node[VERT_OFFSET_CORRECTION] >> correction.second.vert_offset_correction;
- #ifdef HAVE_NEW_YAMLCPP
- if (node[HORIZ_OFFSET_CORRECTION])
- node[HORIZ_OFFSET_CORRECTION] >>
- correction.second.horiz_offset_correction;
- #else
- if (const YAML::Node *pName = node.FindValue(HORIZ_OFFSET_CORRECTION))
- *pName >> correction.second.horiz_offset_correction;
- #endif
- else
- correction.second.horiz_offset_correction = 0;
- const YAML::Node * max_intensity_node = NULL;
- #ifdef HAVE_NEW_YAMLCPP
- if (node[MAX_INTENSITY]) {
- const YAML::Node max_intensity_node_ref = node[MAX_INTENSITY];
- max_intensity_node = &max_intensity_node_ref;
- }
- #else
- if (const YAML::Node *pName = node.FindValue(MAX_INTENSITY))
- max_intensity_node = pName;
- #endif
- if (max_intensity_node) {
- float max_intensity_float;
- *max_intensity_node >> max_intensity_float;
- correction.second.max_intensity = floor(max_intensity_float);
- }
- else {
- correction.second.max_intensity = 255;
- }
- const YAML::Node * min_intensity_node = NULL;
- #ifdef HAVE_NEW_YAMLCPP
- if (node[MIN_INTENSITY]) {
- const YAML::Node min_intensity_node_ref = node[MIN_INTENSITY];
- min_intensity_node = &min_intensity_node_ref;
- }
- #else
- if (const YAML::Node *pName = node.FindValue(MIN_INTENSITY))
- min_intensity_node = pName;
- #endif
- if (min_intensity_node) {
- float min_intensity_float;
- *min_intensity_node >> min_intensity_float;
- correction.second.min_intensity = floor(min_intensity_float);
- }
- else {
- correction.second.min_intensity = 0;
- }
- node[FOCAL_DISTANCE] >> correction.second.focal_distance;
- node[FOCAL_SLOPE] >> correction.second.focal_slope;
- // Calculate cached values
- correction.second.cos_rot_correction =
- cosf(correction.second.rot_correction);
- correction.second.sin_rot_correction =
- sinf(correction.second.rot_correction);
- correction.second.cos_vert_correction =
- cosf(correction.second.vert_correction);
- correction.second.sin_vert_correction =
- sinf(correction.second.vert_correction);
- correction.second.laser_ring = 0; // clear initially (set later)
- }
- /** Read entire calibration file. */
- void operator >> (const YAML::Node& node, Calibration& calibration)
- {
- int num_lasers;
- node[NUM_LASERS] >> num_lasers;
- float distance_resolution_m;
- node[DISTANCE_RESOLUTION] >> distance_resolution_m;
- const YAML::Node& lasers = node[LASERS];
- calibration.laser_corrections.clear();
- calibration.num_lasers = num_lasers;
- calibration.distance_resolution_m = distance_resolution_m;
- calibration.laser_corrections.resize(num_lasers);
- for (int i = 0; i < num_lasers; i++) {
- std::pair<int, LaserCorrection> correction;
- lasers[i] >> correction;
- const int index = correction.first;
- if( index >= calibration.laser_corrections.size() )
- {
- calibration.laser_corrections.resize( index+1 );
- }
- calibration.laser_corrections[index] = (correction.second);
- calibration.laser_corrections_map.insert(correction);
- }
- // For each laser ring, find the next-smallest vertical angle.
- //
- // This implementation is simple, but not efficient. That is OK,
- // since it only runs while starting up.
- double next_angle = -std::numeric_limits<double>::infinity();
- for (int ring = 0; ring < num_lasers; ++ring) {
- // find minimum remaining vertical offset correction
- double min_seen = std::numeric_limits<double>::infinity();
- int next_index = num_lasers;
- for (int j = 0; j < num_lasers; ++j) {
- double angle = calibration.laser_corrections[j].vert_correction;
- if (next_angle < angle && angle < min_seen) {
- min_seen = angle;
- next_index = j;
- }
- }
- if (next_index < num_lasers) { // anything found in this ring?
- // store this ring number with its corresponding laser number
- calibration.laser_corrections[next_index].laser_ring = ring;
- next_angle = min_seen;
- // if (calibration.ros_info) {
- // printf("laser_ring[%2u] = %2u, angle = %+.6f",
- // next_index, ring, next_angle);
- // }
- }
- }
- }
- YAML::Emitter& operator << (YAML::Emitter& out,
- const std::pair<int, LaserCorrection> correction)
- {
- out << YAML::BeginMap;
- out << YAML::Key << LASER_ID << YAML::Value << correction.first;
- out << YAML::Key << ROT_CORRECTION <<
- YAML::Value << correction.second.rot_correction;
- out << YAML::Key << VERT_CORRECTION <<
- YAML::Value << correction.second.vert_correction;
- out << YAML::Key << DIST_CORRECTION <<
- YAML::Value << correction.second.dist_correction;
- out << YAML::Key << TWO_PT_CORRECTION_AVAILABLE <<
- YAML::Value << correction.second.two_pt_correction_available;
- out << YAML::Key << DIST_CORRECTION_X <<
- YAML::Value << correction.second.dist_correction_x;
- out << YAML::Key << DIST_CORRECTION_Y <<
- YAML::Value << correction.second.dist_correction_y;
- out << YAML::Key << VERT_OFFSET_CORRECTION <<
- YAML::Value << correction.second.vert_offset_correction;
- out << YAML::Key << HORIZ_OFFSET_CORRECTION <<
- YAML::Value << correction.second.horiz_offset_correction;
- out << YAML::Key << MAX_INTENSITY <<
- YAML::Value << correction.second.max_intensity;
- out << YAML::Key << MIN_INTENSITY <<
- YAML::Value << correction.second.min_intensity;
- out << YAML::Key << FOCAL_DISTANCE <<
- YAML::Value << correction.second.focal_distance;
- out << YAML::Key << FOCAL_SLOPE <<
- YAML::Value << correction.second.focal_slope;
- out << YAML::EndMap;
- return out;
- }
- YAML::Emitter& operator <<
- (YAML::Emitter& out, const Calibration& calibration)
- {
- out << YAML::BeginMap;
- out << YAML::Key << NUM_LASERS <<
- YAML::Value << calibration.laser_corrections.size();
- out << YAML::Key << DISTANCE_RESOLUTION <<
- YAML::Value << calibration.distance_resolution_m;
- out << YAML::Key << LASERS << YAML::Value << YAML::BeginSeq;
- for (std::map<int, LaserCorrection>::const_iterator
- it = calibration.laser_corrections_map.begin();
- it != calibration.laser_corrections_map.end(); it++)
- {
- out << *it;
- }
- out << YAML::EndSeq;
- out << YAML::EndMap;
- return out;
- }
- void Calibration::read(const std::string& calibration_file) {
- std::ifstream fin(calibration_file.c_str());
- if (!fin.is_open()) {
- initialized = false;
- return;
- }
- initialized = true;
- try {
- YAML::Node doc;
- #ifdef HAVE_NEW_YAMLCPP
- fin.close();
- doc = YAML::LoadFile(calibration_file);
- #else
- YAML::Parser parser(fin);
- parser.GetNextDocument(doc);
- #endif
- doc >> *this;
- } catch (YAML::Exception &e) {
- std::cerr << "YAML Exception: " << e.what() << std::endl;
- initialized = false;
- }
- fin.close();
- }
- void Calibration::write(const std::string& calibration_file) {
- std::ofstream fout(calibration_file.c_str());
- YAML::Emitter out;
- out << *this;
- fout << out.c_str();
- fout.close();
- }
-
- } /* velodyne_pointcloud */
|