raw_snapshot.cpp
Go to the documentation of this file.
00001 
00033 #include <ros/ros.h>
00034 #include <ros/topic.h>
00035 #include <rosbag/bag.h>
00036 #include <multisense_ros/DeviceInfo.h>
00037 #include <multisense_ros/RawCamConfig.h>
00038 #include <multisense_ros/RawCamCal.h>
00039 #include <multisense_ros/RawCamData.h>
00040 #include <multisense_ros/RawLidarData.h>
00041 #include <multisense_ros/RawLidarCal.h>
00042 #include <multisense_lib/MultiSenseTypes.hh>
00043 #include <stdio.h>
00044 #include <ros/callback_queue.h>
00045 
00046 #include <dynamic_reconfigure/DoubleParameter.h>
00047 #include <dynamic_reconfigure/StrParameter.h>
00048 #include <dynamic_reconfigure/Reconfigure.h>
00049 #include <dynamic_reconfigure/Config.h>
00050 
00051 namespace { // anonymous
00052 
00053 #define TOPIC_DEVICE_INFO     "/multisense/calibration/device_info"
00054 #define TOPIC_RAW_CAM_CAL     "/multisense/calibration/raw_cam_cal"
00055 #define TOPIC_RAW_CAM_CONFIG  "/multisense/calibration/raw_cam_config"
00056 #define TOPIC_RAW_CAM_DATA    "/multisense/calibration/raw_cam_data"
00057 #define TOPIC_RAW_LIDAR       "/multisense/calibration/raw_lidar_data"
00058 #define TOPIC_RAW_LIDAR_CAL   "/multisense/calibration/raw_lidar_cal"
00059 
00060 //
00061 // Helper class for getting a full rotation of laser scan data
00062 
00063 class LaserHelper {
00064 public:
00065 
00066     LaserHelper() : motion_started_(false) {}
00067 
00068     void callback(const multisense_ros::RawLidarData::ConstPtr& msg)
00069     {
00070         //
00071         // Keep around one scan until the head starts spinning, then
00072         // start collecting
00073 
00074         if (motion_started_ || 0 == scans_.size())
00075             scans_.push_back(msg);
00076 
00077         if (!motion_started_) {
00078             std::list<multisense_ros::RawLidarData::ConstPtr>::const_iterator it = scans_.begin();
00079 
00080             if (msg->angle_start != (*it)->angle_start) {
00081                 motion_started_ = true;
00082                 scans_.clear();
00083                 scans_.push_back(msg);
00084             }
00085         }
00086     }
00087 
00088     //
00089     // Check if we have received an entire rotation of laser data
00090     // return True if we have a full rotation of data data
00091 
00092     bool done() const
00093     {
00094         std::list<multisense_ros::RawLidarData::ConstPtr>::const_iterator it;
00095 
00096         //
00097         // If we have no scans, then we're definitely not done
00098 
00099         it = scans_.begin();
00100         if (scans_.end() == it)
00101             return false;
00102 
00103         //
00104         // Calculate the total angle swept through all the scans, accounting for wrap-around
00105 
00106         double previous_start = (*it)->angle_start / 1000000.0;
00107         double total_swept    = 0.0;
00108 
00109         for (it = scans_.begin(); it != scans_.end(); it++) {
00110 
00111             double current_start = (*it)->angle_start / 1000000.0;
00112             double current_swept = current_start - previous_start;
00113 
00114             //
00115             // Unwrap the swept angle
00116 
00117             while(current_swept > M_PI)
00118                 current_swept -= 2*M_PI;
00119             while(current_swept < -M_PI)
00120                 current_swept += 2*M_PI;
00121 
00122             //
00123             // Accumulate
00124 
00125             total_swept += current_swept;
00126 
00127             //
00128             // Save the previous start angle
00129 
00130             previous_start = current_start;
00131         }
00132 
00133         return ( fabs(total_swept) > 2.0 * M_PI);
00134     }
00135 
00136     //
00137     // Gets an entire rotation of laser data.  This method constructs it own subscriber
00138     // and callback queue, and services them itself.
00139     // It will return list of the captured messages for this single rotation
00140 
00141     bool getRotation(std::list<multisense_ros::RawLidarData::ConstPtr>& scan_collection)
00142     {
00143         scans_.clear();
00144         ros::NodeHandle nh;
00145         nh.setCallbackQueue(&queue_);
00146 
00147         ros::Subscriber sub_ = nh.subscribe<multisense_ros::RawLidarData>(TOPIC_RAW_LIDAR, 5,
00148                                             boost::bind(&LaserHelper::callback, this, _1));
00149 
00150         ros::Time start = ros::Time::now();
00151 
00152         //
00153         // Service our own callback queue
00154 
00155         while(1) {
00156 
00157             queue_.callOne(ros::WallDuration(1.0));
00158 
00159             if (done()) {
00160                 scan_collection = scans_;
00161                 return true;
00162             }
00163 
00164             if ((ros::Time::now().toSec() - start.toSec()) >= SCAN_COLLECT_TIMEOUT)
00165                 return false;
00166         }
00167     }
00168 
00169 private:
00170 
00171 #if __cplusplus >= 201103
00172     static constexpr double SCAN_COLLECT_TIMEOUT = 20.0; // seconds
00173 #else
00174     static const double SCAN_COLLECT_TIMEOUT = 20.0; // seconds
00175 #endif
00176 
00177     bool motion_started_;
00178     ros::CallbackQueue queue_;
00179     std::list<multisense_ros::RawLidarData::ConstPtr> scans_;
00180 };
00181 
00182 void setConf(const dynamic_reconfigure::Config& conf)
00183 {
00184     dynamic_reconfigure::ReconfigureRequest  srv_req;
00185     dynamic_reconfigure::ReconfigureResponse srv_resp;
00186 
00187     srv_req.config = conf;
00188 
00189     ros::service::call("/multisense/set_parameters", srv_req, srv_resp);
00190 }
00191 
00192 void setMotorSpeed(double radPerSec)
00193 {
00194     dynamic_reconfigure::DoubleParameter double_param;
00195     dynamic_reconfigure::Config          conf;
00196 
00197     double_param.name  = "motor_speed";
00198     double_param.value = radPerSec;
00199     conf.doubles.push_back(double_param);
00200 
00201     setConf(conf);
00202 }
00203 
00204 void setResolution(const std::string& res)
00205 {
00206     dynamic_reconfigure::StrParameter str_param;
00207     dynamic_reconfigure::Config       conf;
00208 
00209     str_param.name  = "resolution";
00210     str_param.value = res;
00211     conf.strs.push_back(str_param);
00212 
00213     setConf(conf);
00214 }
00215 
00216 }; // anonymous
00217 
00218 int main(int    argc,
00219          char** argvPP)
00220 {
00221     ros::init(argc, argvPP, "raw_snapshot");
00222     ros::NodeHandle nh;
00223 
00224     if (argc != 2 ||
00225         std::string(argvPP[1]) == "--help" ||
00226         std::string(argvPP[1]) == "-h") {
00227 
00228         printf("Usage: %s <out_bag_filename>\n", argvPP[0]);
00229         return -1;
00230     }
00231 
00232     std::string outfile(argvPP[1]);
00233 
00234     printf("Capturing device information... "); fflush(stdout);
00235     multisense_ros::DeviceInfo::ConstPtr device_info = ros::topic::waitForMessage<multisense_ros::DeviceInfo>(TOPIC_DEVICE_INFO, nh);
00236     if (!device_info) {
00237         printf("  Error capturing DeviceInfo. Exiting\n");
00238         return -1;
00239     }
00240     printf("  Success\n");
00241 
00242     switch(device_info->imagerType) {
00243     case crl::multisense::system::DeviceInfo::IMAGER_TYPE_CMV2000_GREY:
00244     case crl::multisense::system::DeviceInfo::IMAGER_TYPE_CMV2000_COLOR:
00245       printf("Imager type is CMV2000; setting resolution to 1024x544x128... ");
00246       setResolution("1024x544x128");
00247       break;
00248     case crl::multisense::system::DeviceInfo::IMAGER_TYPE_CMV4000_GREY:
00249     case crl::multisense::system::DeviceInfo::IMAGER_TYPE_CMV4000_COLOR:
00250       printf("Imager type is CMV4000; setting resolution to 1024x1024x128... ");
00251       setResolution("1024x1024x128");
00252       break;
00253     default:
00254       printf("Imager type is not recognized; not setting resolution... ");
00255       printf("  Error setting imager resolution.  Exiting\n");
00256       return -1;
00257       break;
00258     }
00259     ros::Duration(1.0).sleep();
00260 
00261     printf("Capturing lidar calibration... ");
00262     multisense_ros::RawLidarCal::ConstPtr lidar_cal = ros::topic::waitForMessage<multisense_ros::RawLidarCal>(TOPIC_RAW_LIDAR_CAL, nh);
00263     if (!lidar_cal) {
00264         printf("  Error capturing RawLidarCal. Exiting\n");
00265         return -1;
00266     }
00267     printf("  Success\n");
00268 
00269     printf("Capturing camera calibration... "); fflush(stdout);
00270     multisense_ros::RawCamCal::ConstPtr cam_cal = ros::topic::waitForMessage<multisense_ros::RawCamCal>(TOPIC_RAW_CAM_CAL, nh);
00271     if (!cam_cal) {
00272         printf("  Error capturing RawCamCal. Exiting\n");
00273         return -1;
00274     }
00275     printf("  Success\n");
00276 
00277     printf("Capturing camera config... "); fflush(stdout);
00278     multisense_ros::RawCamConfig::ConstPtr cam_config = ros::topic::waitForMessage<multisense_ros::RawCamConfig>(TOPIC_RAW_CAM_CONFIG, nh);
00279     if (!cam_config) {
00280         printf("  Error capturing RawCamConfig. Exiting\n");
00281         return -1;
00282     }
00283     printf("  Success\n");
00284 
00285     printf("Capturing a single left-rectified/disparity image pair... "); fflush(stdout);
00286     multisense_ros::RawCamData::ConstPtr cam_data = ros::topic::waitForMessage<multisense_ros::RawCamData>(TOPIC_RAW_CAM_DATA, nh);
00287     if (!cam_data) {
00288         printf("  Error capturing RawCamData. Exiting\n");
00289         return -1;
00290     }
00291     printf("  Success\n");
00292 
00293     printf("Capturing a full rotation of lidar scans... "); fflush(stdout);
00294 
00295     setMotorSpeed(0.785);
00296 
00297     LaserHelper laser_helper;
00298     std::list<multisense_ros::RawLidarData::ConstPtr> raw_lidar_data;
00299 
00300     if (false == laser_helper.getRotation(raw_lidar_data)) {
00301         printf("  Error capturing RawLidarData...\n");
00302         return -1;
00303     }
00304     printf("  Captured %zu lidar scans\n", raw_lidar_data.size());
00305 
00306     setMotorSpeed(0.0);
00307 
00308     //
00309     // Save all of the data to a bag file
00310 
00311     printf("Saving data to file [%s]\n", outfile.c_str());
00312     rosbag::Bag bag;
00313     bag.open(outfile, rosbag::bagmode::Write);
00314 
00315     bag.write(TOPIC_DEVICE_INFO, ros::TIME_MIN, *device_info);
00316     bag.write(TOPIC_RAW_LIDAR_CAL, ros::TIME_MIN, *lidar_cal);
00317     bag.write(TOPIC_RAW_CAM_CAL, ros::TIME_MIN, *cam_cal);
00318     bag.write(TOPIC_RAW_CAM_CONFIG, ros::TIME_MIN, *cam_config);
00319     bag.write(TOPIC_RAW_CAM_DATA, ros::TIME_MIN, *cam_data);
00320 
00321     std::list<multisense_ros::RawLidarData::ConstPtr>::const_iterator it;
00322     for (it = raw_lidar_data.begin(); it != raw_lidar_data.end(); it++)
00323         bag.write(TOPIC_RAW_LIDAR, ros::TIME_MIN, **it);
00324 
00325     bag.close();
00326     printf("  Success\n");
00327 
00328     return 0;
00329 }
00330 


multisense_ros
Author(s):
autogenerated on Fri Apr 5 2019 02:28:29