streamer.cpp
Go to the documentation of this file.
00001 
00005 #include "streamer.hpp"
00006 
00007 #include "cxcore.h"
00008 #include "highgui.h"
00009 
00010 int main(int argc, char **argv) {
00011         
00012         ros::init(argc, argv, "streamer");
00013         
00014         ros::NodeHandle private_node_handle("~");
00015         
00016         streamerData startupData;
00017         
00018         startupData.read_addr = argv[0];
00019         startupData.read_addr = startupData.read_addr.substr(0, startupData.read_addr.size()-12);
00020         bool inputIsValid = startupData.obtainStartingData(private_node_handle);
00021         
00022         if (!inputIsValid) {
00023                 ROS_ERROR("Configuration invalid!\n");
00024                 return -1;
00025         }
00026 
00027         ros::NodeHandle nh;
00028                 
00029         if (startupData.verboseMode) { ROS_INFO("Establishing streamer node..."); }
00030         boost::shared_ptr < streamerNode > streamer_node (new streamerNode (nh, startupData));
00031         
00032         globalNodePtr = &streamer_node;
00033         
00034         signal(SIGINT, mySigintHandler);
00035         
00036         //streamerNode streamer_node(nh, startupData);
00037         
00038         if (wantsToShutdown) {
00039                 ros::shutdown();
00040 
00041                 return 0;
00042         }
00043         
00044         
00045         if ((startupData.subscribeMode) || (startupData.resampleMode)) {
00046                 streamer_node->runBag();
00047         }
00048         
00049         if (startupData.readMode) {
00050                 streamer_node->runRead();
00051         }
00052         
00053         if (startupData.loadMode) {
00054                 streamer_node->runLoad();
00055         }
00056         
00057         if ((startupData.captureMode) || (startupData.pollMode)) {      
00058                 streamer_node->runDevice();
00059         }
00060         
00061         ros::shutdown();
00062 
00063         return 0;
00064         
00065 }
00066 
00067 void streamerNode::prepareForTermination() {
00068         if (ofs.is_open()) {
00069                 ofs.close();
00070         }
00071         
00072         if (ofs_call_log.is_open()) {
00073                 ofs_call_log.close();
00074         }
00075         
00076         if (ofs_retrieve_log.is_open()) {
00077                 ofs_retrieve_log.close();
00078         }
00079         
00080         if (ofs_internal_log.is_open()) {
00081                 ofs_internal_log.close();
00082         }
00083         
00084         if (ofs_write_log.is_open()) {
00085                 ofs_write_log.close();
00086         }
00087         
00088         if (ofs_duplicates_log.is_open()) ofs_duplicates_log.close();
00089         
00090         if (ofs_thermistor_log.is_open()) ofs_thermistor_log.close();
00091         
00092         if (configData.serialComms) {
00093                 close(mainfd);
00094         }
00095         
00096         releaseDevice();
00097         
00098 }
00099 
00100 void mySigintHandler(int sig)
00101 {
00102         // Do some custom action.
00103         // For example, publish a stop message to some other nodes.
00104 
00105         ROS_INFO("Requested shutdown... terminating feeds...");
00106         wantsToShutdown = true;
00107         
00108         
00109         (*globalNodePtr)->prepareForTermination();
00110 
00111         
00112 
00113         //shutdown();
00114 
00115         // All the default sigint handler does is call shutdown()
00116   
00117 }
00118 
00119 bool streamerNode::setupDevice() {
00120         
00121         if (configData.verboseMode) { ROS_INFO("Entered setupDevice()..."); }
00122         
00123         if (deviceCreated) { return false; }
00124         
00125         //ROS_WARN("%d ; %s", configData.device_num, configData.capture_device.c_str());
00126         
00127         colourMat.release();
00128         
00129         if ((configData.inputDatatype == DATATYPE_8BIT) || (configData.inputDatatype == DATATYPE_MM)) {
00130                 
00131                 if (configData.verboseMode) { ROS_INFO("Setting up device in 8-bit/MM mode..."); }
00132                 getVideoCapture()->open(configData.device_num);
00133         } else if (configData.inputDatatype == DATATYPE_RAW) {
00134                 if (configData.verboseMode) { ROS_INFO("Setting up device in 16-bit mode..."); }
00135                 
00136                 int deviceWidth, deviceHeight;
00137                 getMainVideoSource()->setup_video_capture(configData.capture_device.c_str(), deviceWidth, deviceHeight, configData.verboseMode);
00138                 
00139                 // Now use this opportunity to test/correct?
00140                 
00141                 if ((!configData.imageDimensionsSpecified) && (!configData.intrinsicsProvided)) {
00142                         // Use these values..
00143                         ROS_INFO("Using image size learned from device initialization (%d, %d)", deviceWidth, deviceHeight);
00144                         globalCameraInfo.imageSize.at<unsigned short>(0, 0) = deviceWidth;
00145                         globalCameraInfo.imageSize.at<unsigned short>(0, 1) = deviceHeight;
00146                         globalCameraInfo.cameraSize = cv::Size(globalCameraInfo.imageSize.at<unsigned short>(0, 0), globalCameraInfo.imageSize.at<unsigned short>(0, 1));
00147         
00148                         overwriteCameraDims();
00149         
00150                 } else {
00151                         // Compare the values to what you are using, and produce a warning if necessary...
00152                         
00153                         if ((globalCameraInfo.cameraSize.width != deviceWidth) || (globalCameraInfo.cameraSize.height != deviceHeight)) {
00154                                 ROS_WARN("Device-based image size estimates (%d, %d) conflict with provided image size (%d, %d)", deviceWidth, deviceHeight, globalCameraInfo.cameraSize.width, globalCameraInfo.cameraSize.height);
00155                         }
00156                         
00157                 }
00158                 
00159         }
00160         
00161         if (configData.verboseMode) { ROS_INFO("Device set up!"); }
00162         
00163         setValidity(true);
00164         deviceCreated = true;
00165         return true;
00166 }
00167 
00168 void streamerNode::releaseDevice() {
00169         
00170         if (!deviceCreated) { return; }
00171         
00172         if ((isVideoValid()) && (configData.verboseMode)) { ROS_INFO("setValidity(false) : releaseDevice()"); }
00173         setValidity(false);
00174         
00175         if ((configData.inputDatatype == DATATYPE_8BIT) || (configData.inputDatatype == DATATYPE_MM)) {
00176                 getVideoCapture()->release();
00177         } else if (configData.inputDatatype == DATATYPE_RAW) {
00178                 
00179                 getMainVideoSource()->close_video_capture();
00180                 
00181         }
00182         
00183         deviceCreated = false;
00184 }
00185 
00186 
00187 bool streamerNode::runDevice() {
00188         
00189         if (configData.captureMode) {
00190                 ROS_INFO("Video stream (device: %d) started...", configData.device_num);
00191         } else if (configData.pollMode) {
00192                 ROS_INFO("Video polling (device: %d) started...", configData.device_num);
00193         }
00194         
00195         setupDevice();
00196         
00197         while (isVideoValid()) {
00198                 
00199                 
00200 
00201                 if (configData.verboseMode){ ROS_INFO("Starting loop.."); }
00202                 if (configData.captureMode) {
00203                                                 
00204                         if (configData.verboseMode){ ROS_INFO("About to spin"); }
00205                         ros::spinOnce();
00206                         if (configData.verboseMode){ ROS_INFO("Spun"); }
00207                         
00208                         
00209                         if (streamCallback()) {
00210                                 
00211                                 
00212                                 
00213                                 if (configData.verboseMode){ ROS_INFO("About to process"); }
00214                                 
00215                                 
00216                                 if (processImage()) {
00217                                 
00218                                         if (configData.verboseMode){ ROS_INFO("Processed image."); }
00219                                         
00220                                         if (readyToPublish && (!configData.serialComms || !updateUSBMode)) {
00221                                                 if (configData.verboseMode){ ROS_INFO("About to publish topics..."); }
00222                                                 publishTopics();                
00223                                                 if (configData.verboseMode){ ROS_INFO("Topics published."); }
00224                                                 writeData();
00225                                                 if (configData.verboseMode){ ROS_INFO("Data written."); }
00226                                         }
00227                                 }
00228                         }
00229                         
00230                         
00231                         
00232                 } else if (configData.pollMode) {
00233                         
00234                         // Want to keep on calling streamCallback until the time is right to capture the frame
00235                         streamCallback(false);
00236                         ros::spinOnce();
00237                         
00238                 }
00239                 
00240                 if (configData.verboseMode){ ROS_INFO("Ending loop."); }
00241         }
00242         
00243         ROS_INFO("About to release device here...");
00244         releaseDevice();
00245         
00246         if (configData.captureMode) {
00247                 ROS_INFO("Video capture terminating...");
00248         } else if (configData.pollMode) {
00249                 ROS_INFO("Video polling terminating...");
00250         }
00251         
00252         return true;
00253 }
00254 
00255 bool streamerNode::runLoad() {
00256         ROS_INFO("Image load started...");
00257         
00258         if (!processFolder()) {
00259                 ROS_ERROR("Processing of folder failed...");
00260                 return false;
00261         }
00262         
00263         do {
00264                 
00265                 frameCounter = 0;
00266                 setValidity(true);
00267                 
00268                 while (isVideoValid()) {
00269                         ros::spinOnce();                        
00270                 }
00271                 
00272         } while (configData.loopMode && !wantsToShutdown);
00273         
00274         return true;
00275         
00276 }
00277 
00278 bool streamerNode::runRead() {
00279         
00280         ROS_INFO("Video reading started...");
00281                 
00282         do {
00283                 
00284                 setValidity(true);
00285                 
00286                 if (configData.verboseMode) { ROS_INFO("Opening file (%s)...", configData.filename.c_str()); }
00287                 if (configData.inputDatatype == DATATYPE_RAW) {
00288                         if (getMainVideoSource()->setup_video_file(configData.filename) < 0) {
00289                                 ROS_ERROR("Source configuration failed.");
00290                                 return false;
00291                         }
00292                 } else if ((configData.inputDatatype == DATATYPE_8BIT) || (configData.inputDatatype == DATATYPE_MM)) {
00293                         getVideoCapture()->open(configData.filename.c_str());
00294                         
00295                         if(!cap.isOpened()) { // check if we succeeded
00296                                 ROS_ERROR("File open failed (using OpenCV).");
00297                                 return false;
00298                         }
00299                         //capture = cvCaptureFromAVI(configData.filename.c_str());
00300                 }       
00301                 
00302                 if (configData.verboseMode) { ROS_INFO("Source configured."); }
00303                 
00304                 while (isVideoValid()) {
00305                         ros::spinOnce();
00306                 }
00307                 
00308                 if (configData.verboseMode) { ROS_INFO("Video complete."); }
00309                 
00310                 if (configData.inputDatatype == DATATYPE_RAW) {
00311                         getMainVideoSource()->close_video_file(configData.filename);
00312                 } else if ((configData.inputDatatype == DATATYPE_8BIT) || (configData.inputDatatype == DATATYPE_MM)) {
00313                         getVideoCapture()->release();
00314                 }
00315 
00316         } while (configData.loopMode && !wantsToShutdown);
00317         
00318         if (configData.verboseMode) { ROS_INFO("Video reading terminating..."); }
00319         
00320         return true;
00321         
00322 }
00323 
00324 bool streamerNode::runBag() {
00325         
00326         if (configData.subscribeMode) {
00327                 ROS_INFO("Subscription started...");
00328         } else if (configData.resampleMode) {
00329                 ROS_INFO("Resampling subscription started...");
00330         }
00331 
00332         while (isVideoValid()) {
00333                 
00334                 ros::spinOnce();
00335                                 
00336         }
00337         
00338         if (configData.subscribeMode) {
00339                 ROS_INFO("Subscription terminating...");
00340         } else if (configData.resampleMode) {
00341                 ROS_INFO("Resampling subscription terminating...");
00342         }
00343         
00344         return true;
00345 }
00346 
00347 
00348 bool streamerNode::processFolder() {
00349         
00350         DIR * dirp;
00351         struct dirent * entry;
00352         
00353         dirp = opendir(configData.folder.c_str());
00354         
00355         if (dirp == NULL) {
00356                 ROS_ERROR("Opening of directory (%s) failed.", configData.folder.c_str());
00357                 return false;
00358         }
00359 
00360         while ((entry = readdir(dirp)) != NULL) {
00361                 if (entry->d_type == DT_REG) { // If the entry is a regular file
00362                         inputList.push_back(string(entry->d_name));
00363                         fileCount++;
00364                 }
00365         }
00366 
00367         closedir(dirp);
00368 
00369         sort(inputList.begin(), inputList.end());
00370 
00371         if(fileCount == -1)     {
00372                 ROS_ERROR("File counting error.\n");
00373                 return false;
00374         }
00375 
00376         ROS_INFO("No. of images in folder = %d\n", fileCount);
00377 
00378         if (fileCount == 0) {
00379                 ROS_ERROR("Returning, because no images are in folder.\n");
00380                 return false;
00381         }
00382         
00383         return true;
00384 }
00385 
00386 void streamerNode::markCurrentFrameAsDuplicate() {
00387         
00388         //camera_info.binning_x = 1; // this one is used for thermistor
00389         camera_info.binning_y = 1; // this one is to be used for duplicates
00390 }
00391 
00392 void streamerNode::updateCameraInfo() {
00393         
00394         //if (configData.verboseMode) { ROS_INFO("Updating camera info..."); }
00395         
00396         
00397         if ((configData.subscribeMode) || (configData.resampleMode)) {
00398                 
00399                 
00400                 
00401                 if (configData.syncMode == SYNCMODE_IMAGEONLY) {
00402                         
00403                         
00404                         
00405                         
00406                         if (configData.useCurrentRosTime) {
00407                                 ros::Time currTime = ros::Time::now();
00408                                 camera_info.header.stamp = currTime;
00409                         } else {
00410                                 camera_info.header.stamp = original_time;
00411                         }
00412                         //
00413                         
00414                         
00415                         //camera_info.header.frame_id = "thermalvis_streamer_optical_frame";
00416                         //camera_info.height = cv_ptr->image.rows;
00417                         //camera_info.width = cv_ptr->image.cols;
00418                         
00419                         
00420                 } else {
00421                         camera_info = original_camera_info;
00422                 }
00423                 
00424                 //ROS_WARN("(%f) -> (%f)", original_camera_info.binning_x, camera_info.binning_x);
00425                 
00426                 memcpy(&newThermistorReading, &camera_info.binning_x, sizeof(float)); // monkey, lastThermistorReading
00427                 
00428                 //ROS_WARN("2: (%f) -> (%f)", original_camera_info.binning_x, camera_info.binning_x);
00429                 
00430                 //if (configData.verboseMode) { ROS_INFO("seq = (%d, %d)", original_camera_info.header.seq, camera_info.header.seq); }
00431                 
00432         } else {
00433 
00434                 
00435                 ros::Time currTime = ros::Time::now();
00436                 
00437                 camera_info.header.stamp = currTime;
00438                 
00439                 if ((configData.captureMode || configData.pollMode) && configData.readThermistor) {
00440                         memcpy(&camera_info.binning_x, &lastThermistorReading, sizeof(float));
00441                         //ROS_WARN("Thermistor value = (%f, %d)", lastThermistorReading, camera_info.binning_x);
00442                 }
00443                 
00444                 
00445                 
00446                 // Internal time..
00447                 memcpy(&camera_info.R[0], &firmwareTime, sizeof(float));
00448                 
00449         }
00450         
00451         if (configData.wantsToMarkDuplicates && lastIsDuplicate) {
00452                 camera_info.binning_y = 1;
00453         } else if (configData.wantsToMarkDuplicates) {
00454                 camera_info.binning_y = 0;
00455         }
00456         
00457         if ((globalCameraInfo.cameraMatrix.rows == 3) && (configData.wantsToUndistort)) {
00458                 for (unsigned int iii = 0; iii < 3; iii++) {
00459                         for (unsigned int jjj = 0; jjj < 3; jjj++) {
00460                                 camera_info.K[iii*3 + jjj] = globalCameraInfo.newCamMat.at<double>(iii,jjj);
00461                         }
00462                 }       
00463                 
00464                 for (unsigned int iii = 0; iii < camera_info.D.size(); iii++) {
00465                         camera_info.D.at(iii) = 0.0;
00466                 }       
00467         }
00468         
00469         msg_color.header = camera_info.header;
00470         msg_16bit.header = camera_info.header;
00471         msg_8bit.header = camera_info.header;
00472         
00473 
00474 }
00475 
00476 void streamerNode::assignCameraInfo() {
00477         
00478         if (configData.verboseMode) { ROS_INFO("Entered assignCameraInfo()..."); }
00479         
00480         char frame_id[256];
00481         sprintf(frame_id, "%s_%s_%s", "thermalvis", nodeName, "optical_frame");
00482         camera_info.header.frame_id = string(frame_id);
00483         msg_color.header.frame_id = string(frame_id);
00484         msg_16bit.header.frame_id = string(frame_id);
00485         msg_8bit.header.frame_id = string(frame_id);
00486         
00487         camera_info.height = globalCameraInfo.imageSize.at<unsigned short>(0, 1); // DEFAULT_IMAGE_HEIGHT
00488         camera_info.width = globalCameraInfo.imageSize.at<unsigned short>(0, 0); // DEFAULT_IMAGE_WIDTH
00489 
00490 
00491         /* use data from extrinsics file
00492         if (globalExtrinsicsData.distCoeffs0.cols != 5) { //*/
00493 
00494         // /* use data from intrinsics file
00495         if (globalCameraInfo.distCoeffs.cols != 5) { //*/
00496 
00497                 camera_info.distortion_model = "rational_polynomial";
00498                 if (configData.verboseMode) { ROS_INFO("Camera model : RATIONAL POLYNOMIAL - (%d) coeffs", globalCameraInfo.distCoeffs.cols); }
00499         } else {
00500                 camera_info.distortion_model = "plumb_bob";
00501                 if (configData.verboseMode) { ROS_INFO("Camera model : PLUMB BOB - (%d) coeffs", globalCameraInfo.distCoeffs.cols); }
00502         }
00503 
00504         camera_info.D.clear();
00505 
00506 
00507         // /* use data from intrinsics file
00508         for (int iii = 0; iii < globalCameraInfo.distCoeffs.cols; iii++) { //orig
00509                         camera_info.D.push_back(globalCameraInfo.distCoeffs.at<double>(0, iii)); //orig
00510         }
00511 
00512         /* use data from extrinsics file
00513         for (int iii = 0; iii < globalExtrinsicsData.distCoeffs0.cols; iii++) {
00514             if (configData.camera_number==0){
00515                 camera_info.D.push_back(globalExtrinsicsData.distCoeffs0.at<double>(0, iii));
00516             }else if(configData.camera_number==1){
00517                 camera_info.D.push_back(globalExtrinsicsData.distCoeffs1.at<double>(0, iii));
00518             }
00519         }
00520         //*/
00521 
00522 
00523         // Assign camera info from intrinsics file
00524         if (globalCameraInfo.cameraMatrix.rows == 3) {
00525                 for (unsigned int iii = 0; iii < 3; iii++) {
00526                         for (unsigned int jjj = 0; jjj < 3; jjj++) {
00527                                 if (configData.wantsToUndistort) {
00528                                         camera_info.K[iii*3 + jjj] = globalCameraInfo.newCamMat.at<double>(iii,jjj); //orig
00529                                 } else {
00530                                         camera_info.K[iii*3 + jjj] = globalCameraInfo.cameraMatrix.at<double>(iii,jjj); //orig
00531                                 }
00532                         }
00533                 }               
00534         }
00535         
00536          // */
00537 
00538         /* use data from extrinsics file
00539         if (globalCameraInfo.cameraMatrix.rows == 3) {
00540                 for (unsigned int iii = 0; iii < 3; iii++) {
00541                         for (unsigned int jjj = 0; jjj < 3; jjj++) {
00542                             if (configData.camera_number==0){
00543                                 camera_info.K[iii*3 + jjj] = globalExtrinsicsData.cameraMatrix0.at<double>(iii,jjj);
00544                             }else if(configData.camera_number==1){
00545                                 camera_info.K[iii*3 + jjj] = globalExtrinsicsData.cameraMatrix1.at<double>(iii,jjj);
00546                             }
00547                         }
00548                 }
00549         } // */
00550 
00551 
00552 
00553         //HGH
00554         if (configData.wantsToAddExtrinsics){
00555             if (configData.camera_number == 0){
00556                 for (unsigned int iii = 0; iii < 3; iii++) {
00557                     for (unsigned int jjj = 0; jjj < 3; jjj++) {
00558                         camera_info.R[iii*3 + jjj] = globalExtrinsicsData.R0.at<double>(iii,jjj);
00559                     }
00560                 }
00561                 for (unsigned int iii = 0; iii < 3; iii++) {
00562                     for (unsigned int jjj = 0; jjj < 4; jjj++) {
00563                         camera_info.P[iii*4 + jjj] = globalExtrinsicsData.P0.at<double>(iii,jjj);
00564                     }
00565                 }
00566             }else if (configData.camera_number == 1){
00567                 for (unsigned int iii = 0; iii < 3; iii++) {
00568                     for (unsigned int jjj = 0; jjj < 3; jjj++) {
00569                         camera_info.R[iii*3 + jjj] = globalExtrinsicsData.R1.at<double>(iii,jjj);
00570                     }
00571                 }
00572                 for (unsigned int iii = 0; iii < 3; iii++) {
00573                     for (unsigned int jjj = 0; jjj < 4; jjj++) {
00574                         camera_info.P[iii*4 + jjj] = globalExtrinsicsData.P1.at<double>(iii,jjj);
00575                     }
00576                 }
00577             }
00578 
00579         } else {
00580                 if (globalCameraInfo.R.rows == 3) {
00581                         for (unsigned int iii = 0; iii < 3; iii++) {
00582                                 for (unsigned int jjj = 0; jjj < 3; jjj++) {
00583                                         camera_info.R[iii*3 + jjj] = globalCameraInfo.R.at<double>(iii,jjj);
00584                                 }
00585                         }
00586                 }
00587 
00588                 if (globalCameraInfo.newCamMat.rows == 3) {
00589                         for (unsigned int iii = 0; iii < 3; iii++) {
00590                                 for (unsigned int jjj = 0; jjj < 3; jjj++) {
00591                                             camera_info.P[iii*4 + jjj] = globalCameraInfo.newCamMat.at<double>(iii,jjj);
00592                                 }
00593                         }
00594                 }
00595         }
00596 
00597 
00598         if (configData.wantsToUndistort) {
00599                 if ((globalCameraInfo.cameraMatrix.rows == 3) && (globalCameraInfo.distCoeffs.cols > 0) && (globalCameraInfo.newCamMat.rows == 3)) {
00600                     //HGH initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalCameraInfo.R, globalCameraInfo.newCamMat, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
00601                     //HGH
00602                     if (configData.wantsToAddExtrinsics){
00603                         if (configData.wantsToRectify){
00604                             if (configData.camera_number == 0){
00605                                 cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalExtrinsicsData.R0, globalExtrinsicsData.P0, globalCameraInfo.cameraSize, CV_32FC1,  map1, map2);
00606                             }else if (configData.camera_number == 1){
00607                                 cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalExtrinsicsData.R1, globalExtrinsicsData.P1, globalCameraInfo.cameraSize, CV_32FC1,  map1, map2);
00608                             }
00609                         }else{
00610                             cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs,  cv::Mat(), globalCameraInfo.newCamMat, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
00611                         }
00612                     }else{
00613                         cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs,  cv::Mat(), globalCameraInfo.newCamMat, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
00614                     }
00615 
00616                 }
00617         }
00618         
00619         if (configData.verboseMode) { ROS_INFO("Camera info assigned."); }
00620         
00621 }
00622 
00623 //HGH
00624 void streamerNode::updateCameraInfoExtrinsics() {
00625     if (configData.verboseMode) { ROS_INFO("Updating camera info..."); }
00626     if (configData.camera_number == 0){
00627         for (unsigned int iii = 0; iii < 3; iii++) {
00628             for (unsigned int jjj = 0; jjj < 4; jjj++) {
00629                 camera_info.P[iii*4 + jjj] = globalExtrinsicsData.P0.at<double>(iii,jjj);
00630             }
00631         }
00632     }else if (configData.camera_number == 1){
00633         for (unsigned int iii = 0; iii < 3; iii++) {
00634             for (unsigned int jjj = 0; jjj < 4; jjj++) {
00635                 camera_info.P[iii*4 + jjj] = globalExtrinsicsData.P1.at<double>(iii,jjj);
00636             }
00637         }
00638     }
00639     if (configData.verboseMode) { ROS_INFO("Camera info updated."); }
00640 }
00641 
00642 bool streamerNode::setCameraInfo(sensor_msgs::SetCameraInfo::Request &req, sensor_msgs::SetCameraInfo::Response &rsp) {
00643 
00644         camera_info = req.camera_info;
00645 
00646         if (configData.verboseMode) { ROS_INFO("calling assignCameraInfo() from setCameraInfo()..."); }
00647         assignCameraInfo();
00648 
00649         if (camera_calibration_parsers::writeCalibrationIni("../camera_parameters.txt", "gscam", camera_info)) {
00650                 ROS_INFO("Camera information written to camera_parameters.txt");
00651                 return true;
00652         }
00653         else {
00654                 ROS_ERROR("Could not write camera_parameters.txt");
00655                 return false;
00656         }
00657 }
00658 
00659 bool streamerNode::streamCallback(bool capture) {
00660         
00661         int currAttempts = 0;
00662         
00663         if (configData.verboseMode) { 
00664                 ros::Time callbackTime = ros::Time::now();
00665                 ROS_INFO("Entered <streamCallback> at (%f)", callbackTime.toSec());
00666         }
00667         
00668         if ((configData.inputDatatype == DATATYPE_8BIT) || (configData.inputDatatype == DATATYPE_MM)) {
00669                 
00670                 if (configData.verboseMode){ ROS_INFO("Updating camera info..."); }
00671                 updateCameraInfo();
00672                 if (configData.verboseMode){ ROS_INFO("Camera info updated."); }
00673                 ofs_call_log << ros::Time::now().toNSec() << endl;
00674                 if (configData.verboseMode){ ROS_INFO("Capturing frame (8-bit/MM)..."); }
00675                 cap >> frame;
00676                 
00677                 if (configData.fixDudPixels) {
00678                         if (configData.verboseMode){ ROS_INFO("Fixing dud pixels..."); }
00679                         fix_bottom_right(frame);
00680                         if (configData.verboseMode){ ROS_INFO("Dud pixels fixed."); }
00681                 }
00682                 
00683                 if (configData.verboseMode){ ROS_INFO("Frame captured."); }
00684                 ofs_retrieve_log << ros::Time::now().toNSec() << endl;
00685         } else if (configData.inputDatatype == DATATYPE_RAW) {
00686                 
00687                 ros::Time callTime, retrieveTime;
00688                 
00689                 callTime = ros::Time::now();
00690                 if (configData.verboseMode) { ROS_INFO("Capturing frame (16-bit)... (%f)", callTime.toSec()); }
00691                 
00692                 //bool frameRead = false;
00693                 while ((configData.maxReadAttempts == 0) || (currAttempts < configData.maxReadAttempts)) {
00694                         // Keep on looping, but if max defined, only until curr attempts is high enough
00695                         
00696                         if (configData.verboseMode){ ROS_INFO("Attempting to capture frame..."); }
00697                         
00698                         if (av_read_frame(mainVideoSource->pIFormatCtx, &(mainVideoSource->oPacket)) != 0) {
00699                                 if (configData.verboseMode){ ROS_WARN("av_read_frame() failed."); }
00700                                 currAttempts++;
00701                                 continue;
00702                         }
00703                         
00704                         if (configData.verboseMode){ ROS_INFO("Frame captured successfully."); }
00705                         
00706                         retrieveTime = ros::Time::now();
00707                         firmwareTime = mainVideoSource->oPacket.pts;
00708                         
00709                         if (configData.verboseMode){ ROS_INFO("Updating camera info..."); }
00710                         updateCameraInfo();
00711                         if (configData.verboseMode){ ROS_INFO("Camera info updated."); }
00712                         
00713                         if (mainVideoSource->bRet < 0) {
00714                                 if (configData.verboseMode) { ROS_WARN("(mainVideoSource->bRet < 0) failed."); }
00715                                 currAttempts++;
00716                                 continue;
00717                         }
00718                         
00719                         if (mainVideoSource->oPacket.stream_index != mainVideoSource->ixInputStream) {
00720                                 if (configData.verboseMode) { ROS_WARN("(mainVideoSource->oPacket.stream_index != mainVideoSource->ixInputStream) failed."); }
00721                                 currAttempts++;
00722                                 continue;
00723                         }
00724                         
00725                         if (configData.verboseMode){ ROS_INFO("Decoding frame..."); }
00726                         avcodec_decode_video2(mainVideoSource->pICodecCtx, mainVideoSource->pFrame, &(mainVideoSource->fFrame),&(mainVideoSource->oPacket));
00727                         if (configData.verboseMode){ ROS_INFO("Frame decoded."); }
00728                         
00729                         av_free_packet(&(mainVideoSource->oPacket));
00730                         if (configData.verboseMode){ ROS_INFO("Frame freed."); }
00731                         
00732                         if (!(mainVideoSource->fFrame)) {
00733                                 if (configData.verboseMode) { ROS_WARN("(!(mainVideoSource->fFrame)) failed."); }
00734                                 currAttempts++;
00735                                 continue;
00736                         }
00737                         
00738                         if (capture) {
00739                                 if (configData.verboseMode){ ROS_INFO("Accepting image..."); }
00740                                 acceptImage((void*) *(mainVideoSource->pFrame->data));
00741                                 if (configData.verboseMode){ ROS_INFO("Image accepted."); }
00742                                 
00743                                 char outbuff[256];
00744                                 
00745                                 uint32_t internal_sec, internal_nsec;
00746                 
00747                                 internal_sec = firmwareTime / 1000000;
00748                                 internal_nsec = (firmwareTime % 1000000) * 1000;
00749                                 
00750                                 //sprintf(outbuff, "%016d000", firmwareTime);
00751                                 sprintf(outbuff, "%010d.%09d", internal_sec, internal_nsec);
00752                                 
00753                                 if (configData.wantsToDumpTimestamps) {
00754                                         ofs_internal_log << outbuff << endl;
00755                                         //ofs_retrieve_log << retrieveTime.toNSec() << endl;
00756                                         //ofs_retrieve_log << retrieveTime.sec << "." << retrieveTime.nsec << endl;
00757                                         char output_time[256];
00758                                         sprintf(output_time,"%010d.%09d", retrieveTime.sec, retrieveTime.nsec);
00759                                         ofs_retrieve_log << output_time << endl;
00760                                         ofs_call_log << callTime.toNSec() << endl;
00761                                 }
00762                                 
00763                         }
00764                         
00765                         // Want to exit loop if it actually worked
00766                         if (configData.verboseMode){ ROS_INFO("Frame read."); }
00767                         break;
00768                         
00769                 }
00770 
00771                 if ((currAttempts >= configData.maxReadAttempts) && (configData.maxReadAttempts != 0))  {
00772                         ROS_ERROR("Frame reading failed after (%d) attempts.", currAttempts);
00773                         setValidity(false);
00774                         return false;
00775                 }
00776                 
00777                 // If it got here, it means it succeeded so one attempt was not recorded...
00778                 if (currAttempts >= 1) {
00779                         ROS_WARN("Frame reading required (%d) attempts.", currAttempts+1);
00780                 }
00781         }
00782         
00783         // processImage();
00784         
00785         //ROS_INFO("Exiting callback.");
00786         if (configData.verboseMode){ ROS_INFO("Exiting callback..."); }
00787         
00788         return true;
00789 }
00790 
00791 void streamerNode::acceptImage(void *ptr) {
00792         
00793         if (temperatureMat.rows == 0) {
00794                 if (canRadiometricallyCorrect) {
00795                         
00796                         temperatureMat = cv::Mat::zeros(camera_info.height, camera_info.width, CV_32FC1);
00797                         
00798                 }
00799         }
00800         
00801         if (configData.inputDatatype == DATATYPE_RAW) {
00802                 if ((frame.rows == 0) || (frame.type() != CV_16UC1)) {
00803                         frame = cv::Mat::zeros(camera_info.height, camera_info.width, CV_16UC1);
00804                 }
00805                 
00806                 if (configData.verboseMode){ ROS_INFO("Copying image data to internal matrix... (%d, %d)", camera_info.width, camera_info.height); }
00807                 memcpy(&(frame.at<unsigned char>(0,0)), ptr, camera_info.width*camera_info.height*2);
00808                 if (configData.verboseMode){ ROS_INFO("Data copied."); }
00809                 
00810                 
00811                 
00812         } else if (configData.inputDatatype == DATATYPE_8BIT) {
00813                 if ((frame.rows == 0) || (frame.type() != CV_8UC1)) {
00814                         frame = cv::Mat::zeros(camera_info.height, camera_info.width, CV_8UC1);
00815                 }
00816                 
00817                 if (configData.verboseMode){ ROS_INFO("Copying image data to internal matrix.... (%d, %d)", camera_info.width, camera_info.height); }
00818                 memcpy(&(frame.at<unsigned char>(0,0)), ptr, camera_info.width*camera_info.height);
00819                 if (configData.verboseMode){ ROS_INFO("Data copied."); }
00820                 
00821         } else if (configData.inputDatatype == DATATYPE_MM){
00822                 if ((frame.rows == 0) || (frame.type() != CV_8UC3)) {
00823                         frame = cv::Mat::zeros(camera_info.height, camera_info.width, CV_8UC3);
00824                 }
00825                 
00826                 if (configData.verboseMode){ ROS_INFO("Copying image data to internal matrix... (%d, %d)", camera_info.width, camera_info.height); }
00827                 memcpy(&(frame.at<unsigned char>(0,0)), ptr, camera_info.width*camera_info.height*3);
00828                 if (configData.verboseMode){ ROS_INFO("Data copied."); }
00829         }
00830 
00831         if (configData.fixDudPixels) {
00832                 if (configData.verboseMode){ ROS_INFO("Fixing dud pixels..."); }
00833                 fix_bottom_right(frame);
00834                 if (configData.verboseMode){ ROS_INFO("Dud pixels fixed."); }
00835         }
00836         
00837 }
00838 
00839 bool streamerNode::processImage() {
00840         
00841         if (frame.rows == 0) {
00842                 return false;
00843         }
00844         
00845         //ros::Time preTime, postTime;
00846         //preTime = ros::Time::now();
00847         
00848         if (configData.wantsToResize) {
00849                 resize(frame, rzMat, cv::Size(configData.desiredCols, configData.desiredRows));
00850                 frame = cv::Mat(rzMat);
00851         }
00852         
00853         
00854         if (configData.wantsToRemoveDuplicates || configData.wantsToMarkDuplicates || configData.wantsToOutputDuplicates) {
00855                 
00856                 if (matricesAreEqual(frame, lastFrame)) {
00857                         
00858                         lastNucPerformed_at_the_earliest = ros::Time::now();            
00859                         
00860                         if (configData.wantsToMarkDuplicates) {
00861                                 // markCurrentFrameAsDuplicate();
00862                                 // ROS_ERROR("DUPLICATED!");
00863                                 lastIsDuplicate = true;
00864                         }
00865                         
00866                         //ROS_INFO("SHOULD GET HERE A.");
00867                         if (configData.wantsToOutputDuplicates) {
00868                                 //ROS_INFO("IS IT WRITING HERE? A");
00869                                 ofs_duplicates_log << "1" << endl;
00870                         } else {
00871                                 //ROS_INFO("WHY HERE? A");
00872                         }
00873                         //
00874                         
00875                         if (configData.wantsToRemoveDuplicates) {
00876                                 if (configData.loadMode) {
00877                                         frameCounter++;
00878                                 }
00879                                 return false;
00880                         }
00881                         
00882                 } else {
00883                         //ROS_ERROR("Not omitting...");
00884                         
00885                         if (configData.wantsToMarkDuplicates) {
00886                                 // markCurrentFrameAsDuplicate();
00887                                 lastIsDuplicate = false;
00888                         }
00889                         
00890                         //ROS_INFO("SHOULD GET HERE.");
00891                         if (configData.wantsToOutputDuplicates) {
00892                                 //ROS_INFO("IS IT WRITING HERE?");
00893                                 ofs_duplicates_log << "0" << endl;
00894                         } else {
00895                                 //ROS_INFO("WHY HERE? B");
00896                         }
00897                         
00898                 }
00899                 
00900                 frame.copyTo(lastFrame);
00901                 
00902         }
00903 
00904         //postTime = ros::Time::now();
00905         //ROS_WARN("1. Elapsed time = (%f)", postTime.toSec()-preTime.toSec());
00906         
00907         if (configData.readThermistor) {
00908                 //ROS_WARN("Writing thermistor value... (%f)", lastThermistorReading);
00909                 //ofs_thermistor_log << lastThermistorReading << endl;
00910         }
00911         
00912 
00913         //HGH
00914          //ROS_INFO("Processing image (%d)...", frameCounter);
00915         if (configData.verboseMode){ROS_INFO("Processing image (%d)...", frameCounter);}
00916 
00917         
00918         if (pastMeanIndex >= (configData.temporalMemory-1)) {
00919                 pastMeanIndex = 0;
00920         } else {
00921                 pastMeanIndex++;
00922         }
00923         
00924         if (configData.inputDatatype == DATATYPE_RAW) {
00925                 
00926                 _16bitMat = cv::Mat(frame);
00927                 
00928                 /*
00929                 if (configData.verboseMode) {
00930                         double currMin, currMax;
00931                         minMaxLoc(_16bitMat, &currMin, &currMax);
00932                         ROS_WARN("Current 16-bit image limits = (%f, %f)", currMin, currMax);
00933                 }
00934                 */
00935                 
00936                 //postTime = ros::Time::now();
00937                 //ROS_WARN("1a. Elapsed time = (%f)", postTime.toSec()-preTime.toSec());
00938                 
00939                 if (configData.normFactor > 0.0) {
00940                                         
00941                         //double currMin, currMax;
00942                         double percentile_levels[2];
00943                         percentile_levels[0] = (configData.normFactor / 2.0);
00944                         percentile_levels[1] = 1.0 - (configData.normFactor / 2.0);
00945                         double percentile_values[2];
00946                         
00947                         findPercentiles(_16bitMat, percentile_values, percentile_levels, 2);
00948                         
00949                         thresholdRawImage(_16bitMat, percentile_values);
00950                         
00951                 }
00952 
00953                 //postTime = ros::Time::now();
00954                 //ROS_WARN("1b. Elapsed time = (%f)", postTime.toSec()-preTime.toSec());
00955                 
00956                 if (canRadiometricallyCorrect && configData.radiometricCorrection) {
00957                         
00958                         // ROS_WARN("Applying radiometric correction with (%f, %f, %f)", lastThermistorReading, configData.minTemperature, configData.maxTemperature);
00959                         
00960                         if (configData.radiometricBias != 0) {
00961                                 _16bitMat += configData.radiometricBias;
00962                         }
00963                         
00964                         radMapper.apply(_16bitMat, temperatureMat, lastThermistorReading, configData.radiometricInterpolation);
00965                         
00966                 }
00967 
00968                 //postTime = ros::Time::now();
00969                 //ROS_WARN("1c. Elapsed time = (%f)", postTime.toSec()-preTime.toSec());
00970                 
00971                 if ((configData.outputColorFlag) || (configData.output8bitFlag) || ((configData.wantsToWrite) && ((configData.outputType == "CV_8UC3") || (configData.outputType == "CV_8UC1")) )) {
00972                         //printf("%s << Applying adaptiveDownsample ... (%d)\n", __FUNCTION__, configData.normMode);
00973                         
00974                         if (configData.verboseMode) { ROS_INFO("Entering here x123..."); }
00975                         
00976                         if ((canRadiometricallyCorrect && configData.radiometricCorrection) || configData.alreadyCorrected) {
00977                                 
00978                                 if (configData.verboseMode) { ROS_INFO("Entering here x124..."); }
00979                                 
00980                                 if (configData.alreadyCorrected) {
00981                                         convertToTemperatureMat(_16bitMat, temperatureMat);
00982                                 }
00983                                 
00984                                 
00985                                 if (configData.autoTemperature) {
00986                                         
00987                                         if (configData.verboseMode) { ROS_INFO("Entering here x125..."); }
00988                                         
00989                                         if (configData.verboseMode) {
00990                                                 double currMin, currMax;
00991                                                 minMaxLoc(temperatureMat, &currMin, &currMax);
00992                                                 ROS_WARN("Current temp image limits = (%f) : (%f, %f)", abs(currMax-currMin), currMin, currMax);
00993                                         }
00994                                         
00995                                         double currMin, currMax, currRange, newMin, newMax;
00996                                         //double percentile_levels[2];
00997                                         //percentile_levels[0] = (configData.normFactor / 2.0);
00998                                         //percentile_levels[1] = 1.0 - (configData.normFactor / 2.0);
00999                                         //double percentile_values[2];
01000                                         
01001                                         minMaxLoc(temperatureMat, &currMin, &currMax);
01002                                         
01003                                         //findPercentiles(temperatureMat, percentile_values, percentile_levels, 2);
01004                                         
01005                                         //if (configData.verboseMode) { ROS_INFO("Temperature limits of (%f, %f) = (%f, %f) C", percentile_levels[0], percentile_levels[1], percentile_values[0], percentile_values[1]); }
01006                                         
01007                                         //currMin = percentile_values[0];
01008                                         //currMax = percentile_values[1];
01009                                         
01010                                         
01011                                         // minMaxLoc(temperatureMat, &currMin, &currMax);
01012                                         
01013                                         if (configData.stepChangeTempScale) {
01014                                                 
01015                                                 currRange = currMax - currMin;
01016                                         
01017                                                 if (currRange < 20.0) {
01018                                                         newMin = floor(currMin);
01019                                                         newMax = ceil(currMax);
01020                                                 } else if (currRange < 50.0) {
01021                                                         newMin = 2*floor(currMin/2);
01022                                                         newMax = 2*ceil(currMax/2);
01023                                                 } else if (currRange < 100.0) {
01024                                                         newMin = 5*floor(currMin/5);
01025                                                         newMax = 5*ceil(currMax/5);
01026                                                 } else if (currRange < 200.0) { 
01027                                                         newMin = 10*floor(currMin/5);
01028                                                         newMax = 10*ceil(currMax/5);
01029                                                 } else if (currRange < 500.0) {
01030                                                         newMin = 20*floor(currMin/5);
01031                                                         newMax = 20*ceil(currMax/5);
01032                                                 } else if (currRange < 1000.0) {
01033                                                         newMin = 50*floor(currMin/5);
01034                                                         newMax = 50*ceil(currMax/5);
01035                                                 } else { 
01036                                                         newMin = 100*floor(currMin/5);
01037                                                         newMax = 100*ceil(currMax/5);
01038                                                 }
01039                                                 
01040                                                 //newMin = max(-50.0, newMin);
01041                                                 //newMax = min(200.0, newMax);
01042                                                 
01043                                                 //ROS_ERROR("currRange = (%f), lastMin/Max = (%f, %f), newMin/Max = (%f, %f)", currRange, lastMinDisplayTemp, lastMaxDisplayTemp, newMin, newMax);
01044                                                 
01045                                                 if ( (abs(newMin - lastMinDisplayTemp) > 0.1*currRange) || (abs(newMax - lastMaxDisplayTemp) > 0.1*currRange) ) {
01046                                                         // So if the change in min or max is more than 30% of the current range, then update..
01047                                                         
01048                                                         ROS_WARN("MIN/MAX for display changed to = (%f, %f)", newMin, newMax);
01049                                                         
01050                                                         lastMinDisplayTemp = newMin;
01051                                                         lastMaxDisplayTemp = newMax;
01052                                                         
01053                                                 }
01054                                                 
01055                                         } else {
01056                                                 lastMinDisplayTemp = currMin;
01057                                                 lastMaxDisplayTemp = currMax;
01058                                         }
01059                                         
01060                                         
01061                                         
01062                                         
01063                                         
01064                                         
01065                                         
01066                                         temperatureDownsample(temperatureMat, preFilteredMat, lastMinDisplayTemp, lastMaxDisplayTemp);
01067                                         
01068                                         //if (configData.verboseMode) { ROS_INFO("Temperature limits of (%f, %f) C", lastMinDisplayTemp, lastMaxDisplayTemp); }
01069                                         
01070                         
01071                                 } else {
01072                                         if (configData.verboseMode) { ROS_INFO("Downsampling with (%f, %f)", configData.minTemperature, configData.maxTemperature); }
01073                                         temperatureDownsample(temperatureMat, preFilteredMat, configData.minTemperature, configData.maxTemperature);
01074                                 }
01075                                 
01076                                 
01077                                 
01078                                 
01079                         } else {
01080                                 if (configData.verboseMode) { ROS_INFO("Entering here x126..."); }
01081                                 adaptiveDownsample(_16bitMat, preFilteredMat, configData.normMode, configData.normFactor); //, configData.filterMode);
01082                         }
01083                 
01084 
01085                 } 
01086                 
01087                 //postTime = ros::Time::now();
01088                 //ROS_WARN("1d. Elapsed time = (%f)", postTime.toSec()-preTime.toSec());
01089                 
01090                 if (configData.output16bitFlag || (configData.wantsToWrite && (configData.outputType == "CV_16UC1"))) {
01091                         
01092                         if (canRadiometricallyCorrect && configData.radiometricCorrection && configData.radiometricRaw) {
01093                                 
01094                                 temperatureDownsample16(temperatureMat, scaled16Mat);
01095 
01096                                 
01097                         } else {
01098                                 
01099                                 scaled16Mat = _16bitMat;
01100                                 
01101                         }
01102                         
01103                 }
01104 
01105                 //postTime = ros::Time::now();
01106                 //ROS_WARN("1e. Elapsed time = (%f)", postTime.toSec()-preTime.toSec());
01107                 
01108         } else if (configData.inputDatatype == DATATYPE_8BIT) {
01109 
01110                 
01111                 //ROS_WARN("Entered.. 2");
01112                 
01113                 if (frame.channels() == 3) {
01114                         
01115                         //ROS_WARN("Entered.. X");
01116                         
01117                         if (firstFrame) {
01118                                 isActuallyGray = checkIfActuallyGray(frame);
01119                                 //ROS_WARN("isGray =(%d)", isActuallyGray);
01120                                 firstFrame = false;
01121                                 
01122                                 if (configData.forceInputGray) {
01123                                         isActuallyGray = true;
01124                                         if (configData.verboseMode) { ROS_INFO("Forcing input images to be considered gray."); }
01125                                 }
01126                         }
01127                         
01128                 }
01129                 
01130                 if ((frame.channels() == 1) || (isActuallyGray)) {
01131                         
01132                         if (frame.channels() == 1) {
01133                                 workingFrame = cv::Mat(frame);
01134                         } else if (isActuallyGray) {
01135                                 if (((configData.outputColorFlag) || (configData.outputType == "CV_8UC3")) || ((configData.output8bitFlag) || (configData.outputType == "CV_8UC1"))) {
01136                                         cvtColor(frame, workingFrame, CV_RGB2GRAY);
01137                                 }
01138                         }
01139 
01140                         //ROS_WARN("Processing...");
01141                         
01142                         // Need to normalize if appropriate
01143                         process8bitImage(workingFrame, preFilteredMat, configData.normMode, configData.normFactor);
01144                         
01145                 } else if (frame.channels() == 3) {
01146                         
01147                         colourMat = cv::Mat(frame);
01148                         
01149                         //ROS_WARN("Processing... @");
01150                         
01151                         if ((configData.output8bitFlag) || (configData.outputType == "CV_8UC1")) {
01152                                 cvtColor(colourMat, preFilteredMat, CV_RGB2GRAY);
01153                         }
01154                         
01155                 }
01156 
01157         } else if (configData.inputDatatype == DATATYPE_MM) {
01158                 
01159                 //ROS_WARN("Entered.. 3");
01160                 
01161                 if (frame.channels() != 3) {
01162                         
01163                         ROS_ERROR("Frames must have 3 channels to be used for multi-modal fusion.");
01164                         
01165                         if (firstFrame) {
01166                                 isActuallyGray = false;
01167                                 firstFrame = false;
01168                         }
01169                         
01170                 } else {
01171                         
01172                         //ROS_ERROR("Processing 3-channel image as an MM...");
01173                 
01174                         // This is where you'll break the image apart and perform fusion...
01175                         
01176                         cv::Mat thermal, visible;
01177                         
01178                         splitMultimodalImage(frame, thermal, visible);
01179                         
01180                         double fusion_params[2];
01181                         fusion_params[0] = max(min(0.5, 0.5 - (fusionFactor/2.0)), 0.0);
01182                         fusion_params[1] = max(min(0.5, 1.0 - (fusionFactor/2.0)), 1.0);
01183 
01184                         colourMap.fuse_image(thermal, visible, colourMat, fusion_params);
01185 
01186                         
01187                         if ((configData.output8bitFlag) || (configData.outputType == "CV_8UC1")) {
01188                                 cvtColor(colourMat, preFilteredMat, CV_RGB2GRAY);
01189                         }
01190                         
01191                 }
01192 
01193         }
01194         
01195         //postTime = ros::Time::now();
01196         //ROS_WARN("2. Elapsed time = (%f)", postTime.toSec()-preTime.toSec());
01197 
01198         
01199         if (configData.filterMode > 0) {
01200                 applyFilter(preFilteredMat, smoothedMat, configData.filterMode, configData.filterParam);
01201         } else {
01202                 smoothedMat = preFilteredMat;
01203         }
01204         
01205         if (configData.temporalSmoothing) {
01206                 if (((configData.outputColorFlag) || ((configData.wantsToWrite) && (configData.outputType == "CV_8UC3"))) || ((configData.output8bitFlag) || ((configData.wantsToWrite) && (configData.outputType == "CV_8UC1")))) {
01207                         // If you want to output any kind of 8-bit format...
01208                         
01209                         cv::Scalar means = mean(smoothedMat);
01210                 
01211                         pastMeans[pastMeanIndex] = means[0];
01212                 
01213                         //ROS_WARN("mean = (%f)", pastMeans[pastMeanIndex]);
01214                         
01215                         double temporalMean = 0.0;
01216                         
01217                         for (int iii = 0; iii < min(frameCounter+1, configData.temporalMemory); iii++) {
01218                                 
01219                                 temporalMean += pastMeans[iii];
01220                                 
01221                         }
01222                         
01223                         temporalMean /= min(frameCounter+1, configData.temporalMemory);
01224                         
01225                         //ROS_WARN("temporalMean = (%f)", temporalMean);
01226 
01227                         // sign gives temporal vs mean
01228                         // 
01229                         shiftDiff = (((temporalMean - pastMeans[pastMeanIndex]) > 0.0) ? 1.0 : (((temporalMean - pastMeans[pastMeanIndex]) < 0.0) ? -1.0 : 0.0)) * min(abs((pastMeans[pastMeanIndex] - temporalMean)), configData.maxIntensityChange);
01230                         
01231                         _8bitMat = smoothedMat + shiftDiff;
01232                         
01233                         //cv::Scalar meanA = mean(_8bitMat);
01234                         //ROS_WARN("8-bit mean = (%f)", meanA[0]);
01235                         
01236                 }
01237                 
01238         } else {
01239                 _8bitMat = smoothedMat;
01240         }
01241 
01242         if ((configData.inputDatatype != DATATYPE_MM) && ((configData.inputDatatype != DATATYPE_8BIT) || (frame.channels() != 3) || isActuallyGray)) {
01243         //if (1) {
01244                 // If it wasn't a 3-channel 8-bit image to start with
01245                 //ROS_ERROR("There...");
01246                 //imshow("x", _8bitMat);
01247                 //waitKey(1);
01248                 
01249                 if ((configData.outputColorFlag) || ((configData.wantsToWrite) && (configData.outputType == "CV_8UC3"))) {
01250                         // And if you want color output
01251                         
01252                         //ROS_INFO("Entered...");
01253 
01254                         colourMap.falsify_image(_8bitMat, colourMat, configData.mapParam);
01255 
01256                 }
01257         }
01258         
01259         //postTime = ros::Time::now();
01260         //ROS_WARN("3. Elapsed time = (%f)", postTime.toSec()-preTime.toSec());
01261 
01262         
01263         if (configData.displayThermistor) { 
01264                 
01265                 // IMPLEMENTING HYSTERESIS
01266                 
01267                 double displayVal;
01268                 
01269                 // Determine if higher than last displayed..
01270                 if (newThermistorReading > lastDisplayed) {
01271                         // Increasing...
01272                         displayVal = newThermistorReading-0.015;
01273                         //ROS_INFO("Increasing from (%f) to (%f), last displayed was (%f), now displaying (%f)", lastThermistorReading, newThermistorReading, lastDisplayed, displayVal);
01274                 } else {
01275                         // Decreasing...
01276                         displayVal = newThermistorReading+0.015;
01277                         //ROS_INFO("Decreasing from (%f) to (%f), last displayed was (%f), now displaying (%f)", lastThermistorReading, newThermistorReading, lastDisplayed, displayVal);
01278                         
01279                 }
01280                 
01281                 displayVal = round(20.0*displayVal)/20.0;
01282                 
01283                 ROS_INFO("Temperature = (%.2f)", displayVal); 
01284                 
01285                 lastDisplayed = displayVal;
01286         }
01287         
01288         frameCounter++;
01289         
01290         if (!readyToPublish) {
01291                 readyToPublish = true;
01292         }
01293         
01294         return true;
01295 
01296 }
01297 
01298 void streamerNode::initializeMessages() {
01299         
01300         
01301         if (configData.output16bitFlag) {
01302                 if (msg_16bit.width == 0) {
01303                         if (_16bitMat.rows != 0) {
01304                                 msg_16bit.width = _16bitMat.cols; 
01305                                 msg_16bit.height = _16bitMat.rows;
01306                                 msg_16bit.encoding = "mono16";
01307                                 msg_16bit.is_bigendian = false;
01308                                 msg_16bit.step = _16bitMat.cols*2;
01309                                 msg_16bit.data.resize(_16bitMat.cols*_16bitMat.rows*2);
01310                         }                       
01311                 }
01312 
01313         }
01314         
01315         if (configData.output8bitFlag) {
01316                 if (msg_8bit.width == 0) {
01317                         if (_8bitMat.rows != 0) {
01318                                 msg_8bit.width = _8bitMat.cols; 
01319                                 msg_8bit.height = _8bitMat.rows;
01320                                 msg_8bit.encoding = "mono8";
01321                                 msg_8bit.is_bigendian = false;
01322                                 msg_8bit.step = _8bitMat.cols*1;
01323                                 msg_8bit.data.resize(_8bitMat.cols*_8bitMat.rows*1);
01324                         }
01325                 }
01326         }
01327         
01328         if (configData.outputColorFlag) {
01329                 if (msg_color.width == 0) {
01330                         if (colourMat.rows != 0) {
01331                                 msg_color.width = colourMat.cols; 
01332                                 msg_color.height = colourMat.rows;
01333                                 msg_color.encoding = "bgr8";
01334                                 msg_color.is_bigendian = false;
01335                                 msg_color.step = colourMat.cols*3;
01336                                 msg_color.data.resize(colourMat.cols*colourMat.rows*3);
01337                         }
01338                 }
01339                 
01340         }
01341 }
01342 
01343 void streamerNode::publishTopics() {
01344 
01345 
01346         initializeMessages();
01347 
01348 
01349         /*
01350         if (alphaChanged) {
01351                         updateMap();
01352         }
01353         */
01354 
01355         bool cameraPublished = false;
01356 
01357         if (configData.wantsToDumpTimestamps) {
01358                         //ROS_WARN("outputFile = (%s)", configData.outputTimeFile.c_str());
01359                         ofs << camera_info.header.stamp.toNSec() << endl;
01360         }
01361 
01362         //cout << camera_info.header.stamp.toNSec() << endl;
01363 
01364         if ((configData.output16bitFlag) || (configData.wantsToWrite &&  (configData.outputType == "CV_16UC1"))) {
01365 
01366                         //_16bitMat_pub.copyTo(testMat);
01367 
01368                         if (configData.wantsToUndistort) {
01369                                         if (scaled16Mat.data == _16bitMat_pub.data) {
01370                                                         _16bitMat_pub = cv::Mat(scaled16Mat.size(), scaled16Mat.type());
01371                                         }
01372 
01373                                         remap(scaled16Mat, _16bitMat_pub, map1, map2, cv::INTER_LINEAR, cv::BORDER_CONSTANT, 0);
01374                         } else {
01375                                         _16bitMat_pub = cv::Mat(scaled16Mat);
01376                         }
01377 
01378                         //if (matricesAreEqual(publishTopics() testMat, _16bitMat_pub)) {
01379                                         //ROS_ERROR("Violation!!");
01380                         //} else {
01381                                         //ROS_WARN("Non-Violation!!");
01382                         //}
01383 
01384                         if (configData.output16bitFlag) {
01385 
01386                                         std::copy(&(_16bitMat_pub.at<char>(0,0)), &(_16bitMat_pub.at<char>(0,0))+(_16bitMat_pub.cols*_16bitMat_pub.rows*2), msg_16bit.data.begin());
01387 
01388 
01389 
01390                                         if (!cameraPublished) {
01391 
01392                                                         pub_16bit.publish(msg_16bit, camera_info);
01393                                                         cameraPublished = true;
01394                                         } else {
01395 
01396                                                         pub_16bit_im.publish(msg_16bit);
01397                                         }
01398 
01399 
01400                                         //HGH
01401                                         if (configData.republishSource==REPUBLISH_CODE_16BIT){
01402 
01403                                                 if (configData.republishNewTimeStamp){
01404                                                         //republish with new time stamps
01405                                                         pub_republish.publish(msg_16bit, camera_info, ros::Time::now());
01406                                                 } else {
01407                                                         pub_republish.publish(msg_16bit, camera_info);
01408                                                 }
01409                                         }
01410 
01411                         }
01412 
01413         }
01414 
01415         if ((configData.output8bitFlag) || (configData.wantsToWrite &&  (configData.outputType == "CV_8UC1"))) {
01416 
01417                         if (configData.wantsToUndistort) {
01418                                         if (_8bitMat.data == _8bitMat_pub.data) {
01419                                                         _8bitMat_pub = cv::Mat(_8bitMat.size(), _8bitMat.type());
01420                                         }
01421 
01422                                         remap(_8bitMat, _8bitMat_pub, map1, map2, cv::INTER_LINEAR, cv::BORDER_CONSTANT, 0);
01423                         } else {
01424                                         _8bitMat_pub = cv::Mat(_8bitMat);
01425                         }
01426 
01427                         if (configData.output8bitFlag) {
01428 
01429                                 //HGH
01430                                 if (configData.drawReticle){
01431                                         line(_8bitMat_pub, cv::Point(0,_8bitMat_pub.rows/2), cv::Point(_8bitMat_pub.cols, _8bitMat_pub.rows/2), cv::Scalar(0),1,8);
01432                                         line(_8bitMat_pub, cv::Point(_8bitMat_pub.cols/2,0), cv::Point(_8bitMat_pub.cols/2, _8bitMat_pub.rows), cv::Scalar(0),1,8);
01433                                 }
01434 
01435                                         std::copy(&(_8bitMat_pub.at<unsigned char>(0,0)), &(_8bitMat_pub.at<unsigned char>(0,0))+(_8bitMat_pub.cols*_8bitMat_pub.rows), msg_8bit.data.begin());
01436 
01437 
01438                                         if (!cameraPublished) {
01439                                                         pub_8bit.publish(msg_8bit, camera_info);
01440 
01441                                                         cameraPublished = true;
01442                                         } else {
01443                                                         pub_8bit_im.publish(msg_8bit);
01444 
01445                                         }
01446 
01447                                         //HGH
01448                                          if (configData.republishSource==REPUBLISH_CODE_8BIT_MONO){
01449 
01450                                                  if (configData.republishNewTimeStamp){
01451                                                          //republish with new time stamps
01452                                                          pub_republish.publish(msg_8bit, camera_info, ros::Time::now());
01453                                                  } else{
01454                                                          pub_republish.publish(msg_8bit, camera_info);
01455                                                  }
01456                                          }
01457 
01458                         }
01459 
01460         }
01461 
01462         if ((configData.outputColorFlag) || (configData.wantsToWrite &&  (configData.outputType == "CV_8UC3"))) {
01463 
01464 
01465                         if (colourMat.rows > 0) {
01466 
01467 
01468                                         if (configData.wantsToUndistort) {
01469                                                         if (colourMat.data == colourMat_pub.data) {
01470                                                                         colourMat_pub = cv::Mat(colourMat.size(), colourMat.type());
01471                                                         }
01472 
01473                                                         remap(colourMat, colourMat_pub, map1, map2, cv::INTER_LINEAR, cv::BORDER_CONSTANT, 0);
01474                                         } else {
01475                                                         colourMat_pub = cv::Mat(colourMat);
01476                                         }
01477 
01478                                         if (configData.outputColorFlag) {
01479 
01480                                                 //HGH
01481                                                 if (configData.drawReticle){
01482                                                         line(colourMat_pub, cv::Point(0,colourMat_pub.rows/2), cv::Point(colourMat_pub.cols, colourMat_pub.rows/2), cv::Scalar(0,255,0),1,8);
01483                                                         line(colourMat_pub, cv::Point(colourMat_pub.cols/2,0), cv::Point(colourMat_pub.cols/2, colourMat_pub.rows), cv::Scalar(0,255,0),1,8);
01484 //                                //overlay lines:
01485 //                                for( int j = 0; j < colourMat_pub.rows; j += 32 ){
01486 //                                    line(colourMat_pub, cv::Point(0, j), cv::Point(colourMat_pub.cols, j), cv::Scalar(0, 255, 0), 1, 8);
01487 //                                }
01488                                                 }
01489 
01490                                                         std::copy(&(colourMat_pub.at<cv::Vec3b>(0,0)[0]), &(colourMat_pub.at<cv::Vec3b>(0,0)[0])+(colourMat_pub.cols*colourMat_pub.rows*3), msg_color.data.begin());
01491 
01492                                                         //if (configData.verboseMode) { ROS_INFO("%s << seq = (%d, %d)", __FUNCTION__, camera_info.header.seq, msg_color.header.seq); }
01493                                                         
01494                                                         if (!cameraPublished) {
01495                                                                         if (configData.verboseMode) { ROS_INFO("%s << Publishing the whole camera...", __FUNCTION__); }
01496                                                                         pub_color.publish(msg_color, camera_info);
01497                                                                         cameraPublished = true;
01498                                                         } else {
01499                                                                         //if (configData.verboseMode) { ROS_INFO("%s << Publishing just the image...", __FUNCTION__); }
01500                                                                         pub_color_im.publish(msg_color);
01501                                                         }
01502 
01503                                                         //HGH
01504                                                          if (configData.republishSource==REPUBLISH_CODE_8BIT_COL){
01505 
01506                                                                  if (configData.republishNewTimeStamp){
01507                                                                          //republish with new time stamps
01508                                                                          pub_republish.publish(msg_color, camera_info, ros::Time::now());
01509                                                                  }else{
01510                                                                          pub_republish.publish(msg_color, camera_info);
01511                                                                  }
01512 
01513                                                          }
01514                                         }
01515 
01516 
01517                                         /*
01518                                         imshow("display", colourMat);
01519                                         waitKey(1);
01520                                         */
01521                         }
01522         }
01523 
01524 
01525 
01526         readyToPublish = false;
01527 
01528 }
01529 
01530 void streamerNode::writeData() {
01531         
01532         if (configData.wantsToWrite) {
01533                 
01534                 //ROS_ERROR("wantsToWrite == true");
01535                                 
01536                 if ((frameCounter-1) != lastWritten) {
01537                         
01538                         //ROS_ERROR("Entered write routine...");
01539                 
01540                         char *outputFilename;
01541                         outputFilename = (char*) malloc(256);
01542                         
01543                         if (configData.loadMode && configData.wantsToKeepNames) {
01544                                 
01545                                 size_t findDot = inputList.at(frameCounter-1).rfind(".");
01546                                 
01547                                 string partialName;
01548                                 partialName = inputList.at(frameCounter-1).substr(0, findDot);
01549                                 
01550                                 sprintf(outputFilename, "%s/%s.%s", configData.outputFolder.c_str(), partialName.c_str(), configData.outputFormatString.c_str());
01551                                 
01552                         } else {
01553                                 sprintf(outputFilename, "%s/frame%06d.%s", configData.outputFolder.c_str(), frameCounter-1, configData.outputFormatString.c_str());
01554                         }
01555                         
01556                         if (configData.verboseMode) { ROS_INFO("Output name = (%s), outputType = (%s)", outputFilename, configData.outputType.c_str()); }
01557                         
01558                         if (configData.outputType == "CV_16UC1") {
01559                                 if (scaled16Mat.rows > 0) {
01560                                         
01561                                         if (configData.outputFormatString == "png") {
01562                                                 imwrite(outputFilename, _16bitMat_pub, configData.outputFileParams);
01563                                         } else if ((configData.outputFormatString == "pgm") || (configData.outputFormatString == "ppm")) {
01564                                                 imwrite(outputFilename, _16bitMat_pub);
01565                                         }
01566                                 }
01567                         } else if (configData.outputType == "CV_8UC3") {
01568                                 if (colourMat.rows > 0) {
01569                                         
01570                                         //ROS_ERROR("Actually writing...");
01571                                         
01572                                         if ((configData.outputFormatString == "png") || (configData.outputFormatString == "jpg")) {
01573                                                 imwrite(outputFilename, colourMat_pub, configData.outputFileParams);
01574                                         } else if ((configData.outputFormatString == "bmp") || (configData.outputFormatString == "ppm")) {
01575                                                 imwrite(outputFilename, colourMat_pub);
01576                                         }
01577                                 }
01578                         } else if (configData.outputType == "CV_8UC1") {
01579                                 if (_8bitMat.rows > 0) {
01580                                         if ((configData.outputFormatString == "png") || (configData.outputFormatString == "jpg")) {
01581                                                 imwrite(outputFilename, _8bitMat_pub, configData.outputFileParams);
01582                                         } else if ((configData.outputFormatString == "bmp") || (configData.outputFormatString == "pgm") || (configData.outputFormatString == "ppm")) {
01583                                                 imwrite(outputFilename, _8bitMat_pub);
01584                                         }
01585                                 }
01586                         }                       
01587                         lastWritten = frameCounter - 1;
01588                 }
01589         }
01590         
01591         if (configData.wantsToEncode) {
01592                 if (!videoInitialized) {
01593                         if (configData.videoType == "CV_16UC1") {
01594                                 // 0 writes uncompressed, 1 gives user option
01595                                 vid_writer.open(configData.outputVideo, CV_FOURCC('P','I','M','1'), ((int) configData.framerate), scaled16Mat.size(), true);
01596                         } else if (configData.videoType == "CV_8UC3") {
01597                                 vid_writer.open(configData.outputVideo, CV_FOURCC('P','I','M','1'), ((int) configData.framerate), colourMat.size()); // , true);
01598                         } else if (configData.videoType == "CV_8UC1") {
01599                                 vid_writer.open(configData.outputVideo, CV_FOURCC('X', 'V', 'I', 'D'), ((int) configData.framerate), _8bitMat.size(), false);
01600                         }
01601                         
01602                         videoInitialized = true;
01603                 }
01604                 
01605                 if (configData.videoType == "CV_16UC1") {
01606                         vid_writer << scaled16Mat;
01607                 } else if (configData.videoType == "CV_8UC3") {
01608                         vid_writer << colourMat;
01609                 } else if (configData.videoType == "CV_8UC1") {
01610                         vid_writer << _8bitMat;
01611                 }
01612 
01613         }
01614 }
01615 
01616 bool streamerNode::performNuc() {
01617         
01618         if (configData.verboseMode) { ROS_INFO("Sending NUC command..."); }
01619         
01620         char localCommand[256];
01621         sprintf(localCommand, "nuc");
01622         if (!sendSerialCommand(localCommand, configData.serialWriteAttempts)) ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, configData.serialWriteAttempts);
01623         
01624         return true;
01625 }
01626 
01627 void streamerNode::serialCallback(const ros::TimerEvent&) {
01628         
01629         if (!configData.serialComms) {
01630                 return;
01631         }
01632         
01633         if (configData.serialPollingRate == 0.0) {
01634                 if (configData.verboseMode) { ROS_INFO("Skipping serial callback because desired frequency is zero (0)."); }
01635                 return;
01636         } else {
01637                 //ROS_WARN("Polling serial device...");
01638                 
01639                 //struct termios options;
01640                 //int tcgetattr_ret = tcgetattr(mainfd, &options);
01641                 //displayTermiosData(options);
01642                 
01643                 if (configData.readThermistor) {
01644                         
01645                         newThermistorReading = getThermistorReading();
01646                         //ROS_INFO("Original reading (%f)...", newThermistorReading);
01647                         
01648                         if ((newThermistorReading < MAX_VALID_THERMISTOR) && (newThermistorReading > MIN_VALID_THERMISTOR)) {
01649                                 
01650                                 //ROS_INFO("DEBUG (%d) : (%f) (%f)", 0, lastThermistorReading, newThermistorReading);
01651                                 
01652                                 if ((lastThermistorReading == -99.0) || ( (lastThermistorReading != -99.0) && (abs(lastThermistorReading - newThermistorReading) < configData.maxThermistorDiff) ) ) {
01653                                 
01654                                 //if ((!isinf(-lastThermistorReading)) || ( (isinf(-lastThermistorReading)) && (abs(lastThermistorReading - newThermistorReading) < configData.maxThermistorDiff))) {
01655                                 
01656                                 //bool initTest = (lastThermistorReading < MAX_VALID_THERMISTOR) && (lastThermistorReading > MIN_VALID_THERMISTOR);
01657                                         
01658                                 //if (isinf(-lastThermistorReading) || (abs(lastThermistorReading - newThermistorReading) < configData.maxThermistorDiff)) {
01659                                         
01660                                         //ROS_INFO("DEBUG (%d)", 1);
01661                                         
01662                                         if (newThermistorReading == 0.0) {
01663                                                 //ROS_ERROR("newThermistorReading = (%f), lastThermistorReading = (%f)", newThermistorReading, lastThermistorReading);
01664                                         }
01665                                         
01666                                         // Update thermistor reading buffer
01667                                         thermistorBuffer[recordedThermistorReadings % MAX_THERMISTOR_READINGS_TO_STORE][0] = ros::Time::now().toSec();
01668                                         thermistorBuffer[recordedThermistorReadings % MAX_THERMISTOR_READINGS_TO_STORE][1] = newThermistorReading;
01669                                         recordedThermistorReadings++;
01670                                         
01671                                         //ofs_thermistor_log << newThermistorReading;
01672                                         
01673                                         if (configData.smoothThermistor) {
01674                                                 double smoothReading = smoothThermistorReading();
01675                                                 
01676                                                 if ((smoothReading < MAX_VALID_THERMISTOR) && (smoothReading > MIN_VALID_THERMISTOR)) {
01677                                                         
01678                                                         //ROS_INFO("DEBUG (%d)", 2);
01679                                                         
01680                                                         if ((abs(smoothReading - newThermistorReading) < configData.maxThermistorDiff)) {
01681                                                                 newThermistorReading = smoothReading;
01682                                                                 //ROS_INFO("Smoothed reading (%f)...", newThermistorReading);
01683                                                                 
01684                                                                 //ofs_thermistor_log << " " << newThermistorReading;
01685                                                         } else {
01686                                                                 //ROS_ERROR("smoothReading vs newThermistorReading = (%f) vs (%f)", smoothReading, newThermistorReading);
01687                                                         }
01688                                                         
01689                                                 } else {
01690                                                         //ROS_ERROR("smoothReading = (%f)", smoothReading);
01691                                                 }
01692                                                 
01693                                                 
01694                                         }
01695         
01696 
01697         
01698                                         //ofs_thermistor_log << endl;
01699                                         lastThermistorReading = newThermistorReading;
01700                                         
01701                                         
01702                                         
01703                                 }
01704                                 
01705                                 
01706                                 
01707                         }
01708                         
01709                         //ROS_INFO("newVal = (%f) vs oldVal = (%f)", newThermistorReading, lastThermistorReading);
01710                         
01711                         // If new value is valid
01712                         //if ((newThermistorReading > MIN_THERMISTOR_READNG) && (newThermistorReading < MAX_THERMISTOR_READING)) {
01713                                 
01714                                 // If the historical value is valid
01715                                 //if (lastThermistorReading != 0.0) {
01716                                         
01717                                         
01718                                 //      if (abs(newThermistorReading - lastThermistorReading) < configData.maxThermistorDiff) {
01719                                 //              lastThermistorReading = newThermistorReading;
01720                                 //      }
01721                                         
01722                                         
01723                                 //} else {
01724                                         //lastThermistorReading = newThermistorReading;
01725                                 //}
01726                                 
01727                         //}
01728                         
01729                         //ROS_WARN("Thermistor value = (%f)", lastThermistorReading);
01730                 }
01731                 
01732                 if (configData.calibrationMode > 0) {
01733                         if (alternateCounter >= configData.alternatePeriod) {
01734                                 
01735                                 char localCommand[256];
01736         
01737                                 if (configData.calibrationMode == CALIBMODE_ALT_OUTPUT) {
01738                                         if (altStatus) {
01739                                                 sprintf(localCommand, "vidout raw");
01740                                         } else {
01741                                                 sprintf(localCommand, "vidout ins");
01742                                         }
01743                                         altStatus = !altStatus;
01744                                 } else if (configData.calibrationMode == CALIBMODE_ALT_SHUTTER) {
01745                                         if (performingNuc) {
01746                                                 
01747                                                 if (configData.verboseMode) { ROS_INFO("About to switch shutter"); }
01748                                                 
01749                                                 if (altStatus) {
01750                                                         sprintf(localCommand, "close");
01751                                                 } else {
01752                                                         sprintf(localCommand, "open");
01753                                                 }
01754                                                 altStatus = !altStatus;
01755                                                 
01756                                         } else {
01757                                                 if (configData.verboseMode) { ROS_INFO("About to perform a NUC"); }
01758                                                 sprintf(localCommand, "nuc");
01759                                         }
01760                                         
01761                                         performingNuc = !performingNuc;
01762                                 } else if (configData.calibrationMode == CALIBMODE_LONG_SHUTTER) {
01763                                         
01764                                         if (configData.verboseMode) { ROS_INFO("About to switch shutter"); }
01765                                         
01766                                         if (altStatus) {
01767                                                 sprintf(localCommand, "close");
01768                                         } else {
01769                                                 sprintf(localCommand, "open");
01770                                         }
01771                                         
01772                                         altStatus = !altStatus;
01773                                 }
01774                                 
01775                                 if (configData.verboseMode) { ROS_INFO("Sending SPECIAL command: (%s)", localCommand); }
01776                                 if (!sendSerialCommand(localCommand, configData.serialWriteAttempts)) ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, configData.serialWriteAttempts);
01777                                                                                         
01778                                 alternateCounter = 0;
01779                         }
01780                         alternateCounter++;
01781                 }
01782                 
01783         }
01784         
01785         bool wantsToPerformNuc = false;
01786         
01787         if (currentNucProtectionMode && currentDesiredNucProtectionMode && (abs(ros::Time::now().toSec() - lastFlagReceived.toSec()) > MAX_TIME_WITHOUT_FLAGS) ) {
01788                 
01789                 if (configData.verboseMode) { ROS_INFO("Timer exceeded for disabled NUC mode, preparing to restore NUC settings..."); }
01790                 
01791                 currentDesiredNucProtectionMode = false;
01792                 updateNucInterval = true;
01793                 wantsToPerformNuc = true;
01794                 
01795         }
01796         
01797         if (currentNucProtectionMode && !currentDesiredNucProtectionMode) {
01798                 
01799                 if (abs(ros::Time::now().toSec() - lastNucPerformed_at_the_earliest.toSec()) > MAX_TIME_WITHOUT_NUC_conservative) {
01800                         wantsToPerformNuc = true;
01801                 }
01802                 
01803         }
01804         
01805         if (wantsToPerformNuc) {
01806                 lastNucPerformed_at_the_earliest = ros::Time::now();
01807                 performNuc();
01808                 
01809         }
01810         
01811         if (updateDetectorMode) {
01812                 
01813                 string detectorCode;
01814                 
01815                 if (configData.detectorMode == DETECTOR_MODE_RAW) {
01816                         detectorCode = "raw";
01817                 } else if (configData.detectorMode == DETECTOR_MODE_LUM) {
01818                         detectorCode = "lum";
01819                 } else if (configData.detectorMode == DETECTOR_MODE_INS) {
01820                         detectorCode = "ins";
01821                 } else if (configData.detectorMode == DETECTOR_MODE_RAD) {
01822                         detectorCode = "rad";
01823                 } else if (configData.detectorMode == DETECTOR_MODE_TMP) {
01824                         detectorCode = "t";
01825                 }
01826                 
01827                 if (configData.verboseMode) { ROS_INFO("Changing detector output..."); }
01828                 char localCommand[256];
01829                 sprintf(localCommand, "vidout %s", detectorCode.substr(0,3).c_str());
01830                 if (!sendSerialCommand(localCommand, configData.serialWriteAttempts)) ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, configData.serialWriteAttempts);
01831 
01832                 char buff[SERIAL_BUFF_SIZE];
01833                 int n = read(mainfd, buff, SERIAL_BUFF_SIZE);
01834                 
01835                 // ROS_INFO("Returned is <%s>", buff);
01836                 
01837                 updateDetectorMode = false;
01838         }
01839         
01840         if (updateUSBMode) {
01841                 
01842                 string usbCode;
01843                 
01844                 
01845                 
01846                 if (configData.usbMode == USB_MODE_16) {
01847                         usbCode = "1";
01848                 } else if (configData.usbMode == USB_MODE_8) {
01849                         usbCode = "2";
01850                 }
01851                 
01852                 
01853                 if (configData.verboseMode) { ROS_INFO("Changing usb output with command..."); }
01854                 char localCommand[256];
01855                 sprintf(localCommand, "usb %s", usbCode.substr(0,usbCode.size()).c_str());
01856                 if (!sendSerialCommand(localCommand, configData.serialWriteAttempts)) ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, configData.serialWriteAttempts);
01857                 
01858                 char buff[SERIAL_BUFF_SIZE];
01859                 int n = read(mainfd, buff, SERIAL_BUFF_SIZE);
01860                 
01861                 // ROS_INFO("Returned is <%s>", buff);
01862                 
01863                 updateUSBMode = false;
01864         }
01865         
01866         if (updateNucInterval) {
01867                 
01868                 //ROS_ERROR("ENTERED AGAIN!");
01869                 
01870                 // Value is in 100ths of a degree centigrade, so pass 20 to trigger change every 0.2 C
01871                 
01872                 double valid_thermLimit;
01873                 int maxInterval;
01874                 
01875                 if (configData.verboseMode) { ROS_INFO("Currently in protection mode (%d), want to be in mode (%d)", currentNucProtectionMode, currentDesiredNucProtectionMode); }
01876                 
01877                 if (currentDesiredNucProtectionMode && !currentNucProtectionMode) {
01878                         valid_thermLimit = 0.0;
01879                         maxInterval = 0;
01880                         if (configData.verboseMode) { ROS_WARN("Disabling NUC settings..."); }
01881                         
01882                 } else if (currentDesiredNucProtectionMode && currentNucProtectionMode) {
01883                         ROS_ERROR("Shouldn't be in here! (%d, %d)", currentNucProtectionMode, currentDesiredNucProtectionMode);
01884                 } else {
01885                         valid_thermLimit = float(int(round(100*configData.maxNucThreshold)))/100.0;
01886                         maxInterval = configData.maxNucInterval;
01887                         if (configData.verboseMode) { ROS_INFO("Updating NUC settings... (%d, %f)", maxInterval, valid_thermLimit); }
01888                         settingsDisabled = false;
01889                 }
01890                 
01891                 if (configData.verboseMode) { ROS_INFO("Sending NUCSET command..."); }
01892                 char localCommand[256];
01893                 sprintf(localCommand, "nucset %d %d %d %.2f", maxInterval, 0, 0, valid_thermLimit);
01894                 if (!sendSerialCommand(localCommand, configData.serialWriteAttempts)) ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, configData.serialWriteAttempts);
01895                 
01896                 char buff[SERIAL_BUFF_SIZE];
01897                 int n = read(mainfd, buff, SERIAL_BUFF_SIZE);
01898                 
01899                 // ROS_INFO("Returned is (%s)", buff);
01900                 
01901                 /*
01902                 int testDelay;
01903                 double testDiff;
01904                 getNucSettingsReading(testDelay, testDiff);
01905                 ROS_WARN("Current nuc settings = (%d, %f)", testDelay, testDiff);
01906                 */
01907                 
01908                 currentNucProtectionMode = currentDesiredNucProtectionMode;
01909 
01910                 updateNucInterval = false;
01911 
01912         }
01913         
01914 }
01915 
01916 bool streamerNode::sendSerialCommand(char *command, int max_attempts) {
01917         
01918         int bytesToWrite = 0;
01919         
01920         // string(serialCommand).substr(0,bytesToWrite-1).c_str(), bytesToWrite
01921 
01922         while (command[bytesToWrite] != '\0') {
01923                 
01924                 bytesToWrite++;
01925         }
01926         bytesToWrite++;
01927         
01928         char *ext_command;
01929         ext_command = new char[bytesToWrite+1];
01930         
01931         for (int iii = 0; iii < bytesToWrite-1; iii++) {
01932                 ext_command[iii] = command[iii];
01933         }
01934         
01935         ext_command[bytesToWrite-1] = '\r';
01936         ext_command[bytesToWrite] = '\0';
01937         
01938         //printf("%s << sending (%s) ...\n", __FUNCTION__, ext_command);
01939         
01940         int attempts = 0, n = 0;
01941         while ((max_attempts == 0) || (attempts < max_attempts)) {
01942                 
01943                 n = write(mainfd, ext_command, bytesToWrite);
01944                 
01945                 if (n == bytesToWrite) {
01946                         if (configData.serialFeedback) { ROS_INFO("Serial write of (%s) was successful.", command); }
01947                         return true;
01948                 }
01949                 attempts++;
01950         }
01951         
01952         if ((n < 0) && (errno == EINTR)) {
01953                 ROS_WARN("write() failed 1");
01954         } else if ( n < 0 ) {
01955                 ROS_WARN("write() failed 2");
01956         } else {
01957                 ROS_WARN("write() failed 3");
01958         }
01959         
01960         return false;
01961 }
01962 
01963 void streamerNode::timerCallback(const ros::TimerEvent&) {
01964         
01965         if (configData.pauseMode) {
01966                 return;
01967         }
01968         
01969         if (configData.captureMode || configData.subscribeMode) {
01970                 return;
01971         }
01972         
01973         if (configData.pollMode || configData.resampleMode) {
01974                 
01975                 if (configData.pollMode) {
01976                         
01977                         //ROS_ERROR("About to call stream");
01978                         
01979                         streamCallback();
01980                         
01981                         //ROS_ERROR("Stream called");
01982                 }
01983                 
01984                 if (processImage()) {
01985                         
01986                         //ROS_ERROR("Processed");
01987                         
01988                         if (readyToPublish) {
01989                                 if (configData.resampleMode) {
01990                                         //updateCameraInfo();
01991                                 }
01992                                 publishTopics();
01993                                 
01994                                 //ROS_ERROR("Published");
01995                                 
01996                                 writeData();
01997                                 
01998                                 //ROS_ERROR("Written");
01999                                 
02000                         }
02001                         
02002                 }
02003                 
02004                 //ROS_ERROR("All done.");
02005                 
02006 
02007                 return;
02008         }
02009         
02010         if (configData.loadMode) {
02011                 
02012                 string filename;
02013                 
02014                 if (configData.folder.at(configData.folder.length()-1) == '/') {
02015                         filename = configData.folder + inputList.at(frameCounter);
02016                 } else {
02017                         filename = configData.folder + "/" + inputList.at(frameCounter);
02018                 }
02019 
02020                 frame = cv::imread(filename, -1);
02021                 
02022                 //ROS_INFO("Read frame (%s)", filename.c_str());
02023                 
02024                 if (processImage()) {
02025                         //ROS_INFO("Image process is true...");
02026                         if (readyToPublish) {
02027                                 //ROS_INFO("Publishing...");
02028                                 updateCameraInfo();
02029                                 publishTopics();
02030                                 writeData();
02031                         }
02032                         
02033                 }
02034                 
02035                 if (frameCounter >= fileCount) {
02036                         if (configData.verboseMode) { ROS_INFO("setValidity(false) : (frameCounter >= fileCount)"); }
02037                         setValidity(false);
02038                 }
02039                 
02040                 return;
02041         }
02042 
02043         bool validFrameRead = true;
02044         
02045         // If in read mode...
02046         if (configData.inputDatatype == DATATYPE_RAW) {
02047 
02048                 do { 
02049                         //ROS_WARN("Attempting to read frame...");
02050                         if (av_read_frame(mainVideoSource->pIFormatCtx, &(mainVideoSource->packet)) != 0) {
02051                                 ROS_WARN("Frame invalid...");
02052                                 validFrameRead = false;
02053                                 break;
02054                         }
02055                         //ROS_WARN("Frame valid!");
02056                 } while (mainVideoSource->packet.stream_index != mainVideoSource->videoStream);
02057 
02058                 
02059                 if (validFrameRead) {
02060 
02061                         
02062                         avcodec_decode_video2(mainVideoSource->pCodecCtx, mainVideoSource->pFrame, &(mainVideoSource->frameFinished), &(mainVideoSource->packet));
02063 
02064                         acceptImage((void*) *(mainVideoSource->pFrame->data));
02065 
02066                         if (processImage()) {
02067                                 if (readyToPublish) {
02068                                         updateCameraInfo();
02069                                         publishTopics();
02070                                         writeData();
02071                                 }
02072                         }
02073 
02074                         
02075 
02076                         av_free_packet(&(mainVideoSource->packet));
02077                         
02078                 } else {
02079                         if (configData.verboseMode) { ROS_INFO("setValidity(false) : (validFrameRead)"); }
02080                         setValidity(false);
02081                 }
02082                 
02083         } else if ((configData.inputDatatype == DATATYPE_8BIT) || (configData.inputDatatype == DATATYPE_MM)) {
02084                 
02085                 if (configData.verboseMode) { ROS_INFO("About to read in frame..."); }
02086                 
02087                 if(!cap.isOpened()) {
02088                         ROS_ERROR("Actually, device isn't open...");
02089                         return;
02090                 } else {
02091                         if (configData.verboseMode) { ROS_INFO("Device is open..."); }
02092                 }
02093                 
02094                 if (configData.verboseMode) { ROS_INFO("framecount = (%f)", cap.get(CV_CAP_PROP_FRAME_COUNT)); }
02095                 
02096                 if (configData.verboseMode) { ROS_INFO("dim = (%f, %f)", cap.get(CV_CAP_PROP_FRAME_WIDTH), cap.get(CV_CAP_PROP_FRAME_HEIGHT)); }
02097                 
02098                 cap >> frame;
02099                 //IplImage* tmp_im = cvQueryFrame(capture);
02100                 //frame = tmp_im;
02101                 
02102                 if (configData.verboseMode) { ROS_INFO("Frame read"); }
02103                 
02104                 //imshow("test", frame);
02105                 //waitKey();
02106                 
02107                 if (&frame == NULL) {
02108                         if (configData.verboseMode) { ROS_INFO("setValidity(false) : (&frame == NULL)"); }
02109                         setValidity(false);
02110                         
02111                 } else {
02112                         if (processImage()) {
02113                                 if (readyToPublish) {
02114                                         updateCameraInfo();
02115                                         publishTopics();
02116                                         writeData();
02117                                 }
02118                         }
02119 
02120 
02121                 }
02122                 
02123         }
02124 }
02125 
02126 void streamerNode::assignDefaultCameraInfo() {
02127         
02128         globalCameraInfo.imageSize = cv::Mat(1, 2, CV_16UC1);
02129         globalCameraInfo.imageSize.at<unsigned short>(0, 1) = DEFAULT_IMAGE_HEIGHT;
02130         globalCameraInfo.imageSize.at<unsigned short>(0, 0) = DEFAULT_IMAGE_WIDTH;
02131         
02132         globalCameraInfo.cameraMatrix = cv::Mat::eye(3, 3, CV_64FC1);
02133         globalCameraInfo.distCoeffs = cv::Mat::zeros(1, 8, CV_64FC1);
02134         globalCameraInfo.newCamMat = cv::Mat::eye(3, 3, CV_64FC1);
02135         globalCameraInfo.cameraSize = cv::Size(globalCameraInfo.imageSize.at<unsigned short>(0, 0), globalCameraInfo.imageSize.at<unsigned short>(0, 1));
02136         
02137 }
02138 
02139 void streamerNode::overwriteCameraDims() {
02140         
02141         camera_info.height = globalCameraInfo.imageSize.at<unsigned short>(0, 1);
02142         camera_info.width = globalCameraInfo.imageSize.at<unsigned short>(0, 0);
02143         
02144 }
02145 
02146 streamerNode::streamerNode(ros::NodeHandle& nh, streamerData startupData) {
02147         
02148         configData = startupData;
02149         
02150         if (configData.wantsToAddExtrinsics) {
02151                 getRectification();
02152                 updateCameraInfoExtrinsics();
02153         }
02154         
02155         sprintf(nodeName, "%s", ros::this_node::getName().substr(1).c_str());
02156         
02157         if (configData.verboseMode) { ROS_INFO("Initializing node (%s)", nodeName); }
02158         
02159         canRadiometricallyCorrect = false;
02160         
02161         deviceCreated = false;
02162         
02163         recordedThermistorReadings = 0;
02164         
02165         settingsDisabled = false;
02166         
02167         currentNucProtectionMode = false; 
02168         wantsToDisableNuc = false;
02169         
02170         lastIsDuplicate = true;
02171         firstCall = true;
02172         updateNucInterval = true;
02173         updateDetectorMode = true;
02174         updateUSBMode = true;
02175         altStatus = true;
02176         performingNuc = false;
02177         alphaChanged = true;
02178         readyToPublish = false;
02179         isActuallyGray = false;
02180         videoInitialized = false;
02181         setValidity(true);
02182         firstFrame = true;
02183     centerPrincipalPoint = true;
02184         firstServerCallbackProcessed = false;
02185         pastMeanIndex = -1;
02186         medianPercentile = 0.50;
02187         alternateCounter = 0;
02188         dodgeTime.sec = 0;
02189         dodgeTime.nsec = 0;
02190         fusionFactor = 0.8;
02191         fileCount = 0;
02192         writeIndex = 0;
02193         frameCounter = 0;
02194         lastWritten = -1;
02195         lastThermistorReading = -99.0;
02196         lastMedian = -1.0;
02197         lastLowerLimit = -1.0;
02198         lastUpperLimit = -1.0;
02199         oldMaxDiff = -1.0;
02200         minVal = 65535.0;
02201         maxVal = 0.0;
02202         
02203         
02204         if (configData.radiometryFile != "radiometryFile") {
02205                 // Does file exist?
02206                 
02207                 cv::Mat sensorLimits, graylevelLimits, mappingMatrix;
02208                 
02209                 if (configData.verboseMode) { ROS_INFO("About to read from (%s)", configData.radiometryFile.c_str()); }
02210                 
02211                 cv::FileStorage fs(configData.radiometryFile, cv::FileStorage::READ);
02212                 fs["sensorLimits"] >> sensorLimits;
02213                 fs["graylevelLimits"] >> graylevelLimits;
02214                 fs["mappingMatrix"] >> mappingMatrix;
02215                 fs.release();
02216                 
02217                 if ((sensorLimits.rows == 0) || (graylevelLimits.rows == 0) || (mappingMatrix.rows == 0)) {
02218                         ROS_ERROR("Provided radiometry file is invalid. Please check.");
02219                         wantsToShutdown = true;
02220                         prepareForTermination();
02221                         return;
02222                 }
02223                 
02224                 /*
02225                 cv::Mat testX, testX2;
02226                 
02227                 cv::normalize(mappingMatrix, testX, 0, 255, cv::NORM_MINMAX);
02228                 
02229                 testX.convertTo(testX2, CV_8UC1);
02230                 
02231                 cv::imshow("mapping", testX2);
02232                 cv::waitKey(1);
02233                 
02234                 double minIntensity, maxIntensity;
02235                 
02236                 minMaxLoc(sensorLimits, &minIntensity, &maxIntensity);
02237                 ROS_ERROR("%f, %f", minIntensity, maxIntensity);
02238                 
02239                 minMaxLoc(mappingMatrix, &minIntensity, &maxIntensity);
02240                 ROS_ERROR("%f, %f", minIntensity, maxIntensity);
02241                 
02242                 minMaxLoc(testX, &minIntensity, &maxIntensity);
02243                 ROS_ERROR("%f, %f", minIntensity, maxIntensity);
02244                 
02245                 minMaxLoc(testX2, &minIntensity, &maxIntensity);
02246                 ROS_ERROR("%f, %f", minIntensity, maxIntensity);
02247                 */
02248                 
02249                 radMapper.update(mappingMatrix, sensorLimits.at<double>(0,0), sensorLimits.at<double>(0,1), graylevelLimits.at<double>(0,0), graylevelLimits.at<double>(0,1));
02250                 
02251                 canRadiometricallyCorrect = true;
02252                 
02253                 /*
02254                 cout << "sensorLimits = " << sensorLimits << endl;
02255                 cout << "graylevelLimits = " << graylevelLimits << endl;
02256                 cout << "mappingMatrix = " << mappingMatrix << endl;
02257                 */
02258         }
02259         
02260         if (configData.serialComms) {
02261                 if (configData.verboseMode) { ROS_INFO("Configuring serial comms..."); }
02262                 if (!configureSerialComms()) {
02263                         ROS_ERROR("Serial comms configuration failed. Shutting down.");
02264                         wantsToShutdown = true;
02265                         prepareForTermination();
02266                         return;
02267                 }
02268         }
02269         
02270         if (configData.verboseMode) { ROS_INFO("configData.serialPollingRate = (%f)", configData.serialPollingRate); }
02271         
02272         if (configData.serialPollingRate > 0.1) {
02273                 if (configData.verboseMode) { ROS_INFO("Initializing serial timer at (%f)", 1.0 / ((double) configData.serialPollingRate)); }
02274                 serial_timer = nh.createTimer(ros::Duration(1.0 / ((double) configData.serialPollingRate)), &streamerNode::serialCallback, this);
02275         } else {
02276                 if (configData.verboseMode) { ROS_INFO("Initializing serial timer at (%f)", DEFAULT_SERIAL_POLLING_RATE); }
02277                 serial_timer = nh.createTimer(ros::Duration(DEFAULT_SERIAL_POLLING_RATE), &streamerNode::serialCallback, this);
02278         }
02279         
02280         it = new image_transport::ImageTransport(nh);
02281         
02282         string info_name = configData.topicname.substr(0, configData.topicname.find_last_of("/") + 1) + "camera_info";
02283         if (configData.verboseMode) { ROS_INFO("configData.topicname = (%s)", info_name.c_str()); }
02284         
02285         if (configData.calibrationMode) {
02286                 ros::Duration(1.0).sleep(); // wait a little bit to ensure that the serial comms has been configured..
02287         }
02288         
02289         if (configData.verboseMode) { ROS_INFO("Initializing camera (%s)", configData.topicname.c_str()); }
02290         
02291         mainVideoSource = new streamerSource;
02292 
02293         std::string camera_name;
02294         
02295         if (configData.outputFolder.size() == 0) {
02296                 configData.outputFolder = configData.read_addr + configData.outputFolder;
02297         } else if (configData.outputFolder[0] != '/') {
02298                 configData.outputFolder = configData.read_addr + configData.outputFolder;
02299         }
02300         
02301         configData.outputTimeFile = configData.outputFolder + "-timestamps.txt";
02302         
02303         if (configData.wantsToDumpTimestamps) {
02304                 ofs.open(configData.outputTimeFile.c_str());
02305         }
02306         
02307         if (configData.intrinsicsProvided) {
02308                 
02309                 if (configData.verboseMode) { ROS_INFO("Reading in calibration data"); }
02310                 
02311                 if (configData.intrinsics[0] != '/') {
02312                         configData.intrinsics = configData.read_addr + configData.intrinsics;
02313                 }
02314                 
02315                 if (configData.verboseMode) { ROS_INFO("intrinsics = %s", configData.intrinsics.c_str()); }
02316                 
02317                 // http://www.mathpirate.net/log/2009/11/26/when-in-doubt-link-debug/
02318                 cv::Mat dummyImage(300, 300, CV_8UC1);
02319                 GaussianBlur(dummyImage, dummyImage, cv::Size(5, 5), 1.5);
02320                 
02321                 
02322                 cv::FileStorage fs(configData.intrinsics, cv::FileStorage::READ);
02323                 fs["imageSize"] >> globalCameraInfo.imageSize;
02324                 fs["cameraMatrix"] >> globalCameraInfo.cameraMatrix;
02325                 fs["distCoeffs"] >> globalCameraInfo.distCoeffs;
02326                 fs["newCamMat"] >> globalCameraInfo.newCamMat;
02327                 fs.release();
02328                 
02329                 if (configData.verboseMode) { ROS_INFO("Calibration data read."); }
02330 
02331                         //HGH
02332                         if (globalCameraInfo.cameraMatrix.empty()){
02333                                 ROS_ERROR("Intrinsics file %s invalid! Please check path and filecontent...\n", configData.intrinsics.c_str());
02334                         }
02335                 
02336                 if (configData.verboseMode) { ROS_INFO("Establishing size (%d, %d).", globalCameraInfo.imageSize.at<unsigned short>(0, 0), globalCameraInfo.imageSize.at<unsigned short>(0, 1)); }
02337                 
02338                 globalCameraInfo.cameraSize = cv::Size(globalCameraInfo.imageSize.at<unsigned short>(0, 0), globalCameraInfo.imageSize.at<unsigned short>(0, 1));
02339                 
02340                 //globalCameraInfo.newCamMat = getOptimalNewCameraMatrix(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalCameraInfo.cameraSize, configData.alpha, globalCameraInfo.cameraSize, validPixROI, centerPrincipalPoint);
02341                 
02342                 
02343                 if (configData.verboseMode) { ROS_INFO("Global params determined."); }
02344                 
02345                 
02346         } else if (configData.imageDimensionsSpecified) {
02347                 
02348                 if (configData.verboseMode) { ROS_INFO("Assigning default intrinsics but with specified image size"); }
02349                 
02350                 assignDefaultCameraInfo();
02351                 
02352                 globalCameraInfo.imageSize.at<unsigned short>(0, 1) = configData.inputHeight;
02353                 globalCameraInfo.imageSize.at<unsigned short>(0, 0) = configData.inputWidth;
02354                 globalCameraInfo.cameraSize = cv::Size(globalCameraInfo.imageSize.at<unsigned short>(0, 0), globalCameraInfo.imageSize.at<unsigned short>(0, 1));
02355                 
02356                 // ROS_INFO("Assigned.");
02357                 
02358         } else {
02359                 if (configData.verboseMode) { ROS_INFO("Assigning default intrinsics..."); }
02360                 
02361                 assignDefaultCameraInfo();
02362                 
02363                 if (configData.verboseMode) { ROS_INFO("Default intrinsics assigned."); }
02364         }
02365         
02366         
02367         //HGH
02368         if (configData.autoAlpha) {
02369                 
02370                 if (configData.intrinsicsProvided) {
02371                         if (configData.verboseMode) { ROS_INFO("Finding auto alpha..."); }
02372                         configData.alpha = findBestAlpha(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalCameraInfo.cameraSize);
02373                         //HGH
02374                         if (configData.verboseMode) { ROS_INFO("Optimal alpha: (%f)", configData.alpha); }
02375                 } else {
02376                         ROS_WARN("Cannot estimate an appropriate alpha coefficient because no intrinsics were provided.");
02377                 }
02378                 
02379         }
02380 
02381         
02382         if (configData.wantsToAddExtrinsics) {
02383                 if (configData.verboseMode) { ROS_INFO("Reading in extrinsics..."); }
02384 
02385                         char rotation_name[256], translation_name[256];
02386 
02387                         sprintf(rotation_name, "R_%d", configData.camera_number);
02388                         sprintf(translation_name, "T%d", configData.camera_number);
02389 
02390                         // http://www.mathpirate.net/log/2009/11/26/when-in-doubt-link-debug/
02391                         cv::Mat dummyImage(300, 300, CV_8UC1);
02392                         GaussianBlur(dummyImage, dummyImage, cv::Size(5, 5), 1.5);
02393 
02394                         cv::FileStorage fs(configData.extrinsics, cv::FileStorage::READ);
02395 
02396                         //HGH
02397                         fs[rotation_name] >> globalCameraInfo.R;
02398                         fs[translation_name] >> globalCameraInfo.T;
02399 
02400                         //used to calculate the individual rotation and projection matrices for rectification depending on alpha
02401                         fs["R"] >> globalExtrinsicsData.R;
02402                         fs["T"] >> globalExtrinsicsData.T;
02403 
02404                         //we need also both camera matrices and distortion coefficients
02405                         fs["cameraMatrix0"] >> globalExtrinsicsData.cameraMatrix0;
02406                         fs["cameraMatrix1"] >> globalExtrinsicsData.cameraMatrix1;
02407                         fs["distCoeffs0"] >> globalExtrinsicsData.distCoeffs0;
02408                         fs["distCoeffs1"] >> globalExtrinsicsData.distCoeffs1;
02409 
02410         fs.release();
02411 
02412                         if (globalExtrinsicsData.R.empty()){
02413                                 ROS_ERROR("Extrinsics file %s invalid! Please check path and filecontent...\n", configData.extrinsics.c_str());
02414                         }
02415 
02416                         globalCameraInfo.cameraSize = cv::Size(globalCameraInfo.imageSize.at<unsigned short>(0, 0), globalCameraInfo.imageSize.at<unsigned short>(0, 1));
02417 
02418                         getRectification();
02419 
02420         } else {
02421 
02422                 globalCameraInfo.R = cv::Mat::eye(3, 3, CV_64FC1);
02423                 globalCameraInfo.T = cv::Mat::zeros(3, 1, CV_64FC1);
02424         }
02425 
02426         if (configData.verboseMode) { ROS_INFO("calling assignCameraInfo() from streamerNode()..."); }
02427         assignCameraInfo();
02428 
02429         if (configData.verboseMode) { ROS_INFO("Initializing video source..."); }
02430         mainVideoSource->initialize_video_source();
02431 
02432         colourMap.load_standard(configData.mapCode, configData.mapParam);
02433         
02434         refreshCameraAdvertisements();
02435         
02436         char cameraInfoName[256];
02437         sprintf(cameraInfoName, "thermalvis/%s/set_camera_info", nodeName);
02438         ros::ServiceServer set_camera_info = nh.advertiseService(cameraInfoName, &streamerNode::setCameraInfo, this);
02439 
02440 
02441         if (configData.framerate > 0.0) {
02442                 configData.pauseMode = false;
02443                 timer = nh.createTimer(ros::Duration(1.0 / ((double) configData.framerate)), &streamerNode::timerCallback, this);
02444         } else {
02445                 configData.pauseMode = true;
02446                 timer = nh.createTimer(ros::Duration(1.0 / 1.0), &streamerNode::timerCallback, this);
02447         }
02448         
02449         // Configure log files
02450         callLogFile = configData.read_addr + "/nodes/streamer/log/call_log.txt";
02451         retrieveLogFile = configData.read_addr + "/nodes/streamer/log/retrieve_log.txt";
02452         internalLogFile = configData.read_addr + "/nodes/streamer/log/internal_log.txt";
02453         writeLogFile = configData.read_addr + "/nodes/streamer/log/write_log.txt";
02454         duplicatesLogFile = configData.outputFolder + "-duplicates.txt";
02455         thermistorLogFile = configData.outputFolder + "-thermistor.txt";
02456 
02457         // &PGRCameraNode::publishImage, this, _1
02458         //f = boost::bind(&streamerNode::serverCallback, this, NULL);
02459         //f = boost::bind(serverCallback, _1, _2);
02460         //server.setCallback(f);
02461         
02462         if (configData.verboseMode) { ROS_INFO("Establishing server callback..."); }
02463         f = boost::bind (&streamerNode::serverCallback, this, _1, _2);
02464     server.setCallback (f);
02465     
02466     if (configData.subscribeMode || configData.resampleMode) {
02467                 if (configData.verboseMode) { ROS_INFO("syncMode: (%d)", configData.syncMode); }
02468                 if (configData.syncMode == SYNCMODE_HARD) {
02469                         camera_sub = it->subscribeCamera(configData.topicname, 1, &streamerNode::handle_camera, this);
02470                 } else if (configData.syncMode == SYNCMODE_SOFT) {
02471                         info_sub = nh.subscribe<sensor_msgs::CameraInfo>(info_name, 1, &streamerNode::handle_info, this);
02472                         image_sub = it->subscribe(configData.topicname, 1, &streamerNode::handle_image, this);
02473                 } else if (configData.syncMode == SYNCMODE_IMAGEONLY) {
02474                         image_sub = it->subscribe(configData.topicname, 1, &streamerNode::handle_image, this);
02475                 }
02476         }
02477         
02478         if (configData.externalNucManagement != "") {
02479                 
02480                 lastFlagReceived = ros::Time::now();
02481                 
02482                 ROS_INFO("Subscribing to external nuc management flag (%s)", configData.externalNucManagement.c_str());
02483                 nuc_management_sub = nh.subscribe<std_msgs::Float32>(configData.externalNucManagement, 1, &streamerNode::handle_nuc_instruction, this);
02484 
02485         }
02486     
02487     // Wait for the first server callback to be processed before continuing..
02488     while (!firstServerCallbackProcessed) { };
02489     
02490     if (configData.wantsToDumpTimestamps) {
02491                 ofs_call_log.open(callLogFile.c_str());
02492                 ofs_retrieve_log.open(retrieveLogFile.c_str());
02493                 ofs_internal_log.open(internalLogFile.c_str());
02494                 ofs_write_log.open(writeLogFile.c_str());
02495         }
02496         
02497         if (configData.wantsToOutputDuplicates) {
02498                 if (configData.verboseMode) { ROS_INFO("Outputting duplicates to (%s)", duplicatesLogFile.c_str()); }
02499                 ofs_duplicates_log.open(duplicatesLogFile.c_str());
02500         }
02501 }
02502 
02503 //HGH
02504 void streamerNode::getRectification(){
02505 
02506     cv::Mat Q;
02507 
02508         cv::stereoRectify(globalExtrinsicsData.cameraMatrix0, globalExtrinsicsData.distCoeffs0, globalExtrinsicsData.cameraMatrix1, globalExtrinsicsData.distCoeffs1,
02509                                   globalCameraInfo.cameraSize,
02510                                   globalExtrinsicsData.R, globalExtrinsicsData.T,
02511                                   globalExtrinsicsData.R0, globalExtrinsicsData.R1, globalExtrinsicsData.P0, globalExtrinsicsData.P1,
02512                                   Q,
02513                                   cv::CALIB_ZERO_DISPARITY, configData.alpha, globalCameraInfo.cameraSize, &globalExtrinsicsData.roi0, &globalExtrinsicsData.roi1);
02514 
02515 //        ROS_WARN("----- CAM Number %d",configData.camera_number);
02516 //        cout << "R0 = " << globalExtrinsicsData.R0 << endl;
02517 //        cout << "P0 = "  << globalExtrinsicsData.P0 << endl;
02518 //        cout << "R1 = " << globalExtrinsicsData.R1 << endl;
02519 //        cout << "P1 = "  << globalExtrinsicsData.P1 << endl;
02520 //        cout << "newCamMat = " << globalCameraInfo.newCamMat << endl;
02521 //        printf("roi0 (%d, %d, %d, %d) ", int(globalExtrinsicsData.roi0.x), int(globalExtrinsicsData.roi0.y), int(globalExtrinsicsData.roi0.width), int(globalExtrinsicsData.roi0.height));
02522 //        printf("roi1 (%d, %d, %d, %d) ", int(globalExtrinsicsData.roi1.x), int(globalExtrinsicsData.roi1.y), int(globalExtrinsicsData.roi1.width), int(globalExtrinsicsData.roi1.height));
02523 //        cout << "configData.alpha = " << configData.alpha << endl;
02524 
02525 }
02526 
02527 void streamerNode::handle_nuc_instruction(const std_msgs::Float32::ConstPtr& nuc_msg) {
02528 //void streamerNode::handle_nuc_instruction(const std_msgs::Float32& nuc_msg) {
02529         
02530         if (configData.verboseMode) { ROS_INFO("Handling NUC instruction: (%f)", nuc_msg->data); }
02531         
02532         lastFlagReceived = ros::Time::now();
02533         
02534         currentDesiredNucProtectionMode = (nuc_msg->data < 0.5);
02535         
02536         if (currentDesiredNucProtectionMode != currentNucProtectionMode) { 
02537                 updateNucInterval = true;
02538         }
02539         
02540         
02541 }
02542 
02543 void streamerNode::handle_info(const sensor_msgs::CameraInfoConstPtr& info_msg) {
02544         
02545         //ROS_ERROR("handle_info");
02546         
02547         if (configData.syncMode != SYNCMODE_SOFT) {
02548                 return;
02549         }
02550         
02551         
02552         if ((!configData.subscribeMode) && (!configData.resampleMode)) {
02553                 return;
02554         }
02555         
02556         if (configData.verboseMode) { ROS_INFO("Copying camera info over..."); }
02557         
02558         
02559         original_camera_info = *info_msg;
02560         
02561         
02562         
02563         info_time = ros::Time::now();
02564         original_time = info_msg->header.stamp;
02565         originalInternalTime = info_msg->R[0];
02566         
02567         original_bx = info_msg->binning_x;
02568         original_by = info_msg->binning_y;
02569         
02570         //cout << "Handling info..." << info_msg->header.stamp.toNSec() << ", " << info_time.toNSec() << endl;
02571         
02572         if (std::abs(image_time.toNSec() - info_time.toNSec()) < configData.soft_diff_limit) {
02573                 //ROS_ERROR("handle_info : image_time == info_time");
02574                 image_time = dodgeTime;
02575         
02576                 act_on_image();
02577         }
02578         
02579         
02580 }
02581 
02582 void streamerNode::refreshCameraAdvertisements() {
02583 
02584 
02585         char colorPubName[256], _16bitPubName[256], _8bitPubName[256];
02586 
02587         sprintf(colorPubName, "thermalvis/%s/image_col", nodeName);
02588         sprintf(_16bitPubName, "thermalvis/%s/image_raw", nodeName);
02589         sprintf(_8bitPubName, "thermalvis/%s/image_mono", nodeName);
02590 
02591         bool cameraAdvertised = false;
02592 
02593         // Once all copies of the returned Publisher object are destroyed, the topic
02594         // will be automatically unadvertised.
02595 
02596         pub_color.shutdown();
02597         pub_color_im.shutdown();
02598         pub_16bit.shutdown();
02599         pub_16bit_im.shutdown();
02600         pub_8bit.shutdown();
02601         pub_8bit_im.shutdown();
02602 
02603         //HGH
02604         pub_republish.shutdown();
02605         pub_republish_im.shutdown();
02606 
02607         char _republishPubName[256];
02608         sprintf(_republishPubName, "%s", configData.republishTopic.c_str());
02609 
02610 
02611 
02612         if (configData.output16bitFlag) {
02613 
02614             //HGH
02615             if (configData.republishSource==REPUBLISH_CODE_16BIT){
02616                 pub_republish = it->advertiseCamera(_republishPubName, 1);
02617             }
02618 
02619                 if (!cameraAdvertised) {
02620                         pub_16bit = it->advertiseCamera(_16bitPubName, 1);
02621 
02622                         cameraAdvertised = true;
02623                 } else {
02624                         pub_16bit_im = it->advertise(_16bitPubName, 1);
02625 
02626                 }
02627 
02628         }
02629 
02630         if (configData.output8bitFlag) {
02631 
02632             //HGH
02633             if (configData.republishSource==REPUBLISH_CODE_8BIT_MONO){
02634                 pub_republish = it->advertiseCamera(_republishPubName, 1);
02635             }
02636 
02637                 if (!cameraAdvertised) {
02638                         pub_8bit = it->advertiseCamera(_8bitPubName, 1);
02639 
02640                         cameraAdvertised = true;
02641                 } else {
02642                         pub_8bit_im = it->advertise(_8bitPubName, 1);
02643 
02644                 }
02645 
02646         }
02647 
02648 
02649         if (configData.outputColorFlag) {
02650             //HGH
02651             if (configData.republishSource==REPUBLISH_CODE_8BIT_COL){
02652                 pub_republish = it->advertiseCamera(_republishPubName, 1);
02653             }
02654                 if (!cameraAdvertised) {
02655                         pub_color = it->advertiseCamera(colorPubName, 1);
02656 
02657                         cameraAdvertised = true;
02658                 } else {
02659                         pub_color_im = it->advertise(colorPubName, 1);
02660 
02661                 }
02662         }
02663 
02664 }
02665 
02666 
02667 void streamerNode::handle_camera(const sensor_msgs::ImageConstPtr& msg_ptr, const sensor_msgs::CameraInfoConstPtr& info_msg) {
02668         
02669         //ROS_ERROR("handle_camera");
02670         
02671         if (configData.syncMode != SYNCMODE_HARD) {
02672                 return;
02673         }
02674         
02675         if ((!configData.subscribeMode) && (!configData.resampleMode)) {
02676                 return;
02677         }
02678         
02679         
02680         
02681         
02682         //ROS_ERROR("Handling an image...");
02683         
02684         //cout << "Handling camera..." << msg_ptr->header.stamp.toNSec() << ", " << image_time.toNSec() << endl;
02685         
02686         if (configData.verboseMode) { ROS_INFO("Copying camera info over..."); }
02687         
02688         original_camera_info = *info_msg;
02689         
02690         if (configData.verboseMode) { ROS_INFO("original_camera_info.header.seq = (%d)", original_camera_info.header.seq); }
02691         
02692         original_time = info_msg->header.stamp;
02693         
02694         //ROS_ERROR("original_bx = (%f)", info_msg->binning_x);
02695         
02696         memcpy(&lastThermistorReading, &info_msg->binning_x, sizeof(float));
02697         
02698         
02699         
02700         //original_bx = 0;
02701         //original_by = 0;
02702         
02703         if (configData.inputDatatype == DATATYPE_DEPTH) {
02704                 cv_ptr = cv_bridge::toCvCopy(msg_ptr, "16UC1");
02705         } else {
02706                 cv_ptr = cv_bridge::toCvCopy(msg_ptr, enc::BGR8);                                       // For some reason it reads as BGR, not gray
02707         }
02708         
02709         
02710         act_on_image();
02711         
02712 }
02713 
02714 void streamerNode::act_on_image() {
02715         
02716         //cout << "Acting on image..." << endl;
02717         
02718         updateCameraInfo();
02719         
02720         newImage = cv::Mat(cv_ptr->image);
02721         
02722         cv::Mat grayImage;
02723         
02724         if (newImage.type() == CV_16UC3) {
02725                 cv::cvtColor(newImage, frame, CV_RGB2GRAY);
02726         } else {
02727                 frame = cv::Mat(newImage);
02728         }
02729         
02730         // OPTRIS HACK
02731         /*
02732         for (unsigned int iii = 0; iii < frame.rows; iii++) {
02733                 for (unsigned int jjj = 0; jjj < frame.cols; jjj++) {
02734                         frame.at<unsigned short>(iii,jjj) = (frame.at<unsigned short>(iii,jjj) > 32768) ? frame.at<unsigned short>(iii,jjj) - 32768 : frame.at<unsigned short>(iii,jjj) + 32768;
02735                 }
02736         }
02737         */
02738         
02739         if (readyToPublish) {
02740                 // This means it still hasn't published the last requested frame
02741                 //return;
02742         } else {
02743                 readyToPublish = true;
02744         }
02745         
02746         
02747         if (!configData.resampleMode) {
02748                 
02749                 if (processImage()) {
02750                         if (readyToPublish) {
02751                                 updateCameraInfo();
02752                                 publishTopics();
02753                                 writeData();
02754                         }
02755                 }
02756                 
02757         }
02758         
02759         return;
02760         
02761 }
02762 
02763 void streamerNode::handle_image(const sensor_msgs::ImageConstPtr& msg_ptr) {
02764         
02765         //ROS_ERROR("handle_image");
02766         
02767         if (configData.syncMode == SYNCMODE_HARD) {
02768                 return;
02769         }
02770         
02771         if ((!configData.subscribeMode) && (!configData.resampleMode)) {
02772                 return;
02773         }
02774 
02775         //cout << "Handling image..." << msg_ptr->header.stamp.toNSec() << ", " << image_time.toNSec() << endl;
02776         
02777         original_time = msg_ptr->header.stamp;
02778         
02779         //ROS_INFO("original_time = (%f)", original_time.toSec());
02780         
02781         image_time = ros::Time::now();
02782         cv_ptr = cv_bridge::toCvCopy(msg_ptr, enc::BGR8);                                       // For some reason it reads as BGR, not gray
02783         
02784         if (configData.syncMode == SYNCMODE_SOFT) {
02785                 if (std::abs(image_time.toNSec() - info_time.toNSec()) < configData.soft_diff_limit) {
02786                         // ROS_ERROR("handle_image : image_time == info_time");
02787                         
02788                         image_time = dodgeTime;
02789                         act_on_image();
02790                 }
02791         } else {
02792                 act_on_image();
02793         }
02794         
02795         
02796         //ROS_ERROR("image header = (%d)", msg_ptr->header.stamp.toNSec());
02797                 
02798         
02799 
02800         
02801 }
02802 
02803 streamerData::streamerData() {
02804         
02805         intrinsicsProvided = false;
02806         //wantsToRectify = false;
02807         //HGH
02808         wantsToAddExtrinsics = false;
02809         wantsToWrite = false;
02810         wantsToEncode = false;
02811         wantsToKeepNames = false;
02812         wantsToUndistort = false;
02813         wantsToResize = false;
02814         loopMode = false;
02815         imageDimensionsSpecified = false;
02816         
02817         
02818         
02819         mapCode = CIECOMP;
02820         mapParam = 0;
02821         
02822         framerate = -1.0;
02823         
02824         soft_diff_limit = 5000000;
02825         
02826 }
02827 
02828 bool streamerData::obtainStartingData(ros::NodeHandle& nh) {
02829         
02830         nh.param<std::string>("source", source, "dev");
02831         
02832         nh.param<std::string>("file", filename, "file");
02833         nh.param<std::string>("dev", capture_device, "/dev/video0");
02834         device_num = atoi(&(capture_device.c_str(), capture_device.at(capture_device.length()-1)));
02835         
02836         nh.param<std::string>("topic", topicname, "/thermalvis/streamer/image_raw");
02837         nh.param<std::string>("externalNucManagement", externalNucManagement, "");
02838         
02839         
02840         nh.param<bool>("serialFeedback", serialFeedback, false);
02841         
02842         nh.param<double>("maxThermistorDiff", maxThermistorDiff, 0.5);
02843         
02844         nh.param<int>("outputFormat", outputFormat, 4);
02845         
02846         nh.param<int>("temporalMemory", temporalMemory, 5);
02847         
02848         nh.param<int>("serialWriteAttempts", serialWriteAttempts, 1);
02849         //nh.param<int>("serialReadAttempts", serialReadAttempts, 1);
02850         
02851         nh.param<int>("alternatePeriod", alternatePeriod, 5);
02852         
02853         if (outputFormat == 0) {
02854                 outputFormatString = "jpg";
02855         } else if (outputFormat == 1) {
02856                 outputFormatString = "pgm";
02857         } else if (outputFormat == 2) {
02858                 outputFormatString = "bmp";
02859         } else if (outputFormat == 3) {
02860                 outputFormatString = "ppm";
02861         } else if (outputFormat == 4) {
02862                 outputFormatString = "png";
02863         }
02864         
02865         nh.param<std::string>("outputType", outputType, "CV_8UC3");
02866         
02867         if (outputType == "CV_8UC3") {
02868                 if (outputFormatString == "pgm") {
02869                         ROS_WARN("PGM cannot write as CV_8UC3...");
02870                 }
02871         } else if (outputType == "CV_8UC1") { 
02872                 // ...
02873         } else if (outputType == "CV_16UC1") {
02874                 if ((outputFormatString == "jpg") || (outputFormatString == "bmp")) {
02875                         ROS_WARN("JPG/BMP cannot write as CV_16UC1...");
02876                 }
02877         } else {
02878                 ROS_WARN("Unrecognized output format (%s)", outputType.c_str());
02879         }
02880 
02881         nh.param<double>("maxIntensityChange", maxIntensityChange, 2.0);
02882 
02883         
02884         nh.param<bool>("drawReticle", drawReticle, false);
02885         nh.param<bool>("displayThermistor", displayThermistor, false);
02886         nh.param<bool>("dumpDuplicates", wantsToOutputDuplicates, false);
02887         nh.param<bool>("fixDudPixels", fixDudPixels, true);
02888         nh.param<bool>("forceInputGray", forceInputGray, false);
02889         nh.param<bool>("stepChangeTempScale", stepChangeTempScale, false);
02890         nh.param<bool>("extremes", extremes, true);
02891         nh.param<bool>("temporalSmoothing", temporalSmoothing, false);
02892         nh.param<bool>("markDuplicates", wantsToMarkDuplicates, false);
02893         nh.param<bool>("smoothThermistor", smoothThermistor, false);
02894         nh.param<double>("thermistorWindow", thermistorWindow, 5.0);
02895         
02896         nh.param<bool>("readThermistor", readThermistor, true);
02897         
02898         nh.param<int>("maxReadAttempts", maxReadAttempts, 0);
02899         
02900         nh.param<int>("filterMode", filterMode, 0);
02901         nh.param<double>("filterParam", filterParam, 2.0);
02902         
02903         
02904         nh.param<std::string>("radiometryFile", radiometryFile, "radiometryFile");
02905         
02906         nh.param<double>("syncDiff", syncDiff, 0.005);
02907         
02908         soft_diff_limit = (unsigned long) (syncDiff * 1000000000.0);
02909         
02910         nh.param<std::string>("portAddress", portAddress, "/dev/ttyUSB0");
02911         
02912         nh.param<bool>("autoAlpha", autoAlpha, true);
02913         nh.param<double>("alpha", alpha, 0.00);
02914         
02915         
02916         nh.param<int>("serialCommsConfigurationCode", serialCommsConfigurationCode, SERIAL_COMMS_CONFIG_DEFAULT);
02917 
02918         nh.param<bool>("useCurrentRosTime", useCurrentRosTime, false);
02919 
02920         //nh.param<int>("map", map, 0);
02921         //nh.param<bool>("extremes", extremes, true);
02922         nh.param<std::string>("intrinsics", intrinsics, "intrinsics");
02923         
02924         nh.param<int>("inputWidth", inputWidth, 0);
02925         nh.param<int>("inputHeight", inputHeight, 0);
02926         
02927         
02928         nh.param<std::string>("extrinsics", extrinsics, "extrinsics");
02929         
02930         //nh.param<int>("inputDatatype", inputDatatype, 1);
02931         
02932     nh.param<int>("camera_number", camera_number, 0);
02933         nh.param<double>("framerate", framerate, -1.0);
02934         
02935         nh.param<double>("writeQuality", writeQuality, 1.0);
02936         
02937         nh.param<bool>("output16bit", output16bitFlag, true);
02938         nh.param<bool>("output8bit", output8bitFlag, false);
02939         nh.param<bool>("outputColor", outputColorFlag, true);
02940         
02941         nh.param<bool>("loopMode", loopMode, false);
02942         
02943         
02944         nh.param<bool>("disableSkimming", disableSkimming, true);
02945         
02946         nh.param<bool>("writeImages", wantsToWrite, false);
02947         nh.param<std::string>("outputFolder", outputFolder, "outputFolder");
02948         
02949         nh.param<bool>("serialComms", serialComms, false);
02950         nh.param<bool>("radiometricCorrection", radiometricCorrection, true);
02951         nh.param<bool>("alreadyCorrected", alreadyCorrected, false);
02952         nh.param<bool>("radiometricRaw", radiometricRaw, false);
02953         nh.param<bool>("radiometricInterpolation", radiometricInterpolation, true);
02954         
02955         nh.param<int>("radiometricBias", radiometricBias, 0);
02956         
02957         nh.param<int>("calibrationMode", calibrationMode, CALIBMODE_OFF);
02958         
02959         ROS_INFO("calibrationMode = (%d)", calibrationMode);
02960         
02961         if (outputFolder.size() > 0) {
02962                 if (outputFolder.at(outputFolder.size()-1) == '/') {
02963                         outputFolder = outputFolder.substr(0, outputFolder.size()-1);
02964                 }
02965         } else {
02966                 ROS_WARN("Specified output folder is 0 characters long - ignoring.");
02967                 outputFolder = "outputFolder";
02968         }
02969         
02970         
02971         if ((wantsToWrite) && (outputFolder.size() > 0)) {
02972                 // Create necessary folders
02973                 char folderCommand[256];
02974                 sprintf(folderCommand, "mkdir -p %s", outputFolder.c_str());
02975                 
02976                 int res = system(folderCommand);
02977                 
02978                 if (res == 0) {
02979                         ROS_WARN("system() call returned 0...");
02980                 }
02981         }
02982         
02983         
02984         if (verboseMode) { ROS_INFO("outputFolder = (%s)", outputFolder.c_str()); }
02985         
02986         
02987         
02988         nh.param<std::string>("outputType", outputType, "CV_16UC1");
02989         
02990         outputFileParams.clear();
02991         int val;
02992         if (outputFormatString == "png") {
02993                 outputFileParams.push_back(CV_IMWRITE_PNG_COMPRESSION);
02994                 val = int((1.0-writeQuality) * 9.0);
02995                 outputFileParams.push_back(val);
02996         } else if (outputFormatString == "jpg") {
02997                 outputFileParams.push_back(CV_IMWRITE_JPEG_QUALITY);
02998                 val = int(writeQuality * 100.0);
02999                 outputFileParams.push_back(val);
03000         }
03001                 
03002         nh.param<bool>("keepOriginalNames", wantsToKeepNames, false);
03003         nh.param<bool>("loopMode", loopMode, false);
03004         
03005         nh.param<bool>("writeVideo", wantsToEncode, false);
03006         nh.param<std::string>("outputVideo", outputVideo, "outputVideo");
03007         nh.param<std::string>("videoType", videoType, "videoType");
03008                 
03009         nh.param<bool>("undistortImages", wantsToUndistort, false);
03010         //HGH
03011         nh.param<bool>("rectifyImages", wantsToRectify, false);
03012         
03013         nh.param<bool>("removeDuplicates", wantsToRemoveDuplicates, false);
03014         
03015         if (outputFolder != "outputFolder") {
03016                 nh.param<bool>("dumpTimestamps", wantsToDumpTimestamps, false);
03017         } else {
03018                 wantsToDumpTimestamps = false;
03019         }
03020         
03021         nh.param<bool>("resizeMode", wantsToResize, false);
03022         
03023         nh.param<int>("syncMode", syncMode, SYNCMODE_HARD);
03024 
03025         // "hardSync", int_t, 0, "Image and camera_info topics must be fully synchronized"),
03026         // "softSync", int_t, 1, "Image and camera_info topics do not have to be fully synchronized"),
03027         // "imageOnly", int_t, 2, "To be used when no camera_info topic is present") ],
03028 
03029 
03030         
03031         nh.param<int>("rows", desiredRows, -1);
03032         nh.param<int>("cols", desiredCols, -1);
03033         
03034         if (wantsToResize) {
03035                 if ((desiredRows < 1) || (desiredRows > MAX_ROWS) || (desiredCols < 1) || (desiredCols > MAX_COLS)) {
03036                         ROS_ERROR("Resizing values (%d, %d) invalid.",desiredCols, desiredRows);
03037                         return false;
03038                         
03039                 } else {
03040                         ROS_INFO("Resizing to (%d x %d)", desiredCols, desiredRows);
03041                 }
03042         }
03043         
03044         if (wantsToUndistort) { ROS_INFO("Undistorting images..."); }
03045         
03046         nh.param<int>("normMode", normMode, 0);
03047         nh.param<std::string>("normalizationMode", normalizationMode, "normalizationMode");
03048         
03049         nh.param<double>("normFactor", normFactor, 0.0);
03050         
03051         if (normalizationMode == "standard") {
03052                 normMode = 0;
03053         } else if (normalizationMode == "low_contrast") {
03054                 normMode = 1;
03055         }
03056         
03057         /*
03058         if (wantsToWrite) {
03059                 ROS_INFO("Has chosen to write.");
03060                 
03061                 if (outputFolder == "outputFolder") {
03062                         ROS_ERROR("outputFolder incorrectly specified...");
03063                         return false;
03064                 } else {
03065                         ROS_INFO("outputFolder = (%s)", outputFolder.c_str());
03066                         
03067                 }
03068                 
03069                 ROS_INFO("Image format = (%d); image type = (%s)", outputFormat, outputType.c_str());
03070                 
03071                 if (wantsToKeepNames) {
03072                         ROS_INFO("(retaining original names)");
03073                 } else {
03074                         ROS_INFO("(not retaining original names)");
03075                 }
03076                 
03077         }
03078         */
03079         
03080         if (wantsToEncode) {
03081                 if (verboseMode) { ROS_INFO("Has chosen to encode."); }
03082                 
03083                 if (outputVideo == "outputVideo") {
03084                         ROS_ERROR("outputVideo incorrectly specified...");
03085                         return false;
03086                 } else {
03087                         ROS_INFO("outputVideo = (%s)", outputVideo.c_str());
03088                         
03089                 }
03090                 
03091                 if (verboseMode) { ROS_INFO("Image format = (%s); image type = (%s)", "avi", videoType.c_str()); }
03092                 
03093         }
03094         
03095         if (inputDatatype == DATATYPE_8BIT) {
03096                 if (verboseMode) { ROS_INFO("Streaming mode: 8-bit"); }
03097         } else if (inputDatatype == DATATYPE_RAW) {
03098                 if (verboseMode) { ROS_INFO("Streaming mode: 16-bit"); }
03099         } else if (inputDatatype == DATATYPE_MM) {
03100                 if (verboseMode) { ROS_INFO("Streaming mode: multimodal"); }
03101         }
03102 
03103         // ROS_INFO("Source = %s", source.c_str());
03104         
03105         readMode = false;
03106         loadMode = false;
03107         captureMode = false;
03108         pollMode = false;
03109         subscribeMode = false;
03110         resampleMode = false;
03111         
03112         
03113         if (source == "dev") {
03114                 
03115                 if ((framerate < 0) || (framerate > MAX_READ_RATE)) {
03116                         if (verboseMode) { ROS_INFO("Framerate set to (%f) so therefore defaulting to capture mode.", framerate); }
03117                         framerate = MAX_READ_RATE;
03118                         captureMode = true;
03119                 } else {
03120                         if (verboseMode) { ROS_INFO("Requested framerate (%f) - polling mode", framerate); }
03121                         pollMode = true;
03122                 }
03123                 
03124                 ROS_INFO("Reading from device (%s)", capture_device.c_str());
03125                 
03126         } else if (source == "file") {
03127                 readMode = true;
03128                 
03129                 if ((framerate < 0.0) || (framerate > MAX_READ_RATE)) {
03130                         ROS_INFO("Invalid framerate (%f) so defaulting to (%f).", framerate, DEFAULT_READ_RATE);
03131                         framerate = DEFAULT_READ_RATE;
03132                 } else {
03133                         ROS_INFO("Requested framerate = %f", framerate);
03134                 }
03135                 
03136                 ROS_INFO("Reading from a file (%s)", filename.c_str());
03137         } else if (source == "folder") {
03138                 
03139                 loadMode = true;
03140                 
03141                 if ((framerate < 0.0) || (framerate > MAX_READ_RATE)) {
03142                         ROS_WARN("Invalid framerate (%f) so defaulting to (%f).", framerate, DEFAULT_READ_RATE);
03143                         framerate = DEFAULT_READ_RATE;
03144                 } else {
03145                         ROS_INFO("Requested framerate = %f", framerate);
03146                 }
03147                 
03148                 ROS_INFO("Loading images from a folder (%s)", folder.c_str());
03149                 
03150                 
03151         } else if (source == "topic") {
03152                 
03153                 ROS_INFO("Subscribing to topic (%s) ", topicname.c_str());
03154                 
03155                 if ((framerate < 0.0) || (framerate > MAX_READ_RATE)) {
03156                         ROS_WARN("Invalid framerate (%f) so defaulting to subscribe mode.", framerate);
03157                         framerate = DEFAULT_READ_RATE;
03158                         subscribeMode = true;
03159                 } else {
03160                         ROS_INFO("Requested framerate = %f (resample mode)", framerate);
03161                         resampleMode = true;
03162                 }
03163                 
03164         }
03165         
03166         
03167         //maxIntensityChange = 100 / DEFAULT_READ_RATE;
03168         
03169         if (loopMode == true) {
03170                 ROS_INFO("Option to loop has been selected.");
03171         }
03172         
03173         if (intrinsics != "intrinsics") {
03174                 intrinsicsProvided = true;
03175                 if (verboseMode) { ROS_INFO("Intrinsics at (%s) selected.", intrinsics.c_str()); }
03176                 
03177                 if ((inputWidth != 0) && (inputHeight != 0)) {
03178                         ROS_WARN("Provided image dimensions will be ignored because of provided intrinsics file.");
03179                 }
03180         } else {
03181                 
03182                 if ((inputWidth != 0) && (inputHeight != 0)) {
03183                         ROS_INFO("Provided image dimensions (%d, %d) will be used.", inputWidth, inputHeight);
03184                         imageDimensionsSpecified = true;
03185                 } else {
03186                         ROS_WARN("No intrinsics or image dimensions provided. Will attempt to estimate camera size...");        
03187                 }
03188                 
03189                         
03190                 //intrinsics = read_addr + "data/calibration/csiro-aslab/miricle-1.yml";
03191                 //ROS_ERROR("No intrinsics supplied. Defaulting to (%s)", intrinsics.c_str());
03192         }
03193         
03194         
03195         
03196         if (extrinsics != "extrinsics") {
03197                 ROS_INFO("Extrinsics at %s selected.", extrinsics.c_str());
03198 
03199                 //HGH
03200                 //wantsToRectify = false;
03201 
03202                 //HGH
03203                 wantsToAddExtrinsics = true;
03204                 if (camera_number < 0) {
03205                         ROS_WARN("Invalid camera number selected (%d) so defaulting to (0).", camera_number);
03206                         camera_number = 0;
03207                         
03208                 } else {
03209                         ROS_INFO("Camera number (%d).", camera_number);
03210                 }
03211                 
03212         }
03213 
03214         getMapping(map, extremes, mapCode, mapParam);
03215                 
03216         int modeCount = 0;
03217         
03218         if (captureMode) modeCount++;
03219         if (pollMode) modeCount++;
03220         if (readMode) modeCount++;
03221         if (loadMode) modeCount++;
03222         if (subscribeMode) modeCount++;
03223         if (resampleMode) modeCount++;
03224         
03225         if (modeCount == 0) {
03226                 ROS_ERROR("Either a device, file or topic should be specified for streaming.");
03227                 return false;
03228         } else if (modeCount > 1) {
03229                 ROS_ERROR("Either a device, file or topic should be specified - not more than one.");
03230                 return false;
03231         }
03232         
03233         if ((framerate < -1.0) || (framerate > MAX_READ_RATE)) {
03234                 framerate = DEFAULT_READ_RATE;
03235         }
03236         
03237          //ROS_INFO("normalization mode = (%d)", normMode);
03238 
03239        //HGH
03240         nh.param<int>("republishSource", republishSource, NO_REPUBLISH_CODE);
03241         nh.param<std::string>("republishTopic", republishTopic, "specifyTopic/image_raw");
03242         //check for valid republishSource
03243         switch(republishSource){
03244         case REPUBLISH_CODE_8BIT_MONO:
03245             ROS_INFO("Republishing mono image as %s", republishTopic.c_str() );
03246             break;
03247         case REPUBLISH_CODE_8BIT_COL:
03248             ROS_INFO("Republishing color image as %s", republishTopic.c_str() );
03249             break;
03250         case REPUBLISH_CODE_16BIT:
03251             ROS_INFO("Republishing 16bit image as %s", republishTopic.c_str() );
03252             break;
03253         default:
03254             republishSource = NO_REPUBLISH_CODE;
03255             break;
03256         }
03257         if (republishSource != NO_REPUBLISH_CODE){
03258             ROS_INFO("Republish Code: %d", republishSource);
03259         }
03260 
03261         nh.param<bool>("republishNewTimeStamp",republishNewTimeStamp,false);
03262 
03263         nh.param<std::string>("frameID", frameID, ""); //specify the frameID
03264 
03265         nh.param<bool>("drawReticle",drawReticle, false);
03266 
03267         
03268         return true;
03269 }
03270 
03271 void getMapping(int mapIndex, bool extremes, int& mapCode, int& mapParam) {
03272         
03273         if (mapIndex == 0) {
03274                 mapCode = GRAYSCALE;
03275         } else if (mapIndex == 1) {
03276                 mapCode = CIECOMP;
03277         } else if (mapIndex == 2) {
03278                 mapCode = BLACKBODY;
03279         } else if (mapIndex == 3) {
03280                 mapCode = RAINBOW;
03281         } else if (mapIndex == 4) {
03282                 mapCode = IRON;
03283         } else if (mapIndex == 5) {
03284                 mapCode = BLUERED;
03285         } else if (mapIndex == 6) {
03286                 mapCode = JET;
03287         } else if (mapIndex == 7) {
03288                 mapCode = CIELUV;
03289         } else if (mapIndex == 8) {
03290                 mapCode = ICEIRON;
03291         } else if (mapIndex == 9) {
03292                 mapCode = ICEFIRE;
03293         } else if (mapIndex == 10) {
03294                 mapCode = REPEATED;
03295         } else if (mapIndex == 11) {
03296                 mapCode = HIGHLIGHTED;
03297         } else {
03298                 mapCode = GRAYSCALE;
03299         }
03300         
03301         if (extremes) {
03302                 mapParam = 0;
03303         } else {
03304                 mapParam = 1;
03305         }
03306         
03307 }
03308 
03309 bool streamerNode::isVideoValid() {
03310         
03311         if (::wantsToShutdown) {
03312                 if (configData.verboseMode){ ROS_INFO("Wants to shut down.."); }
03313                 setValidity(false);
03314         }       
03315                 
03316         return videoValid;
03317         
03318 }
03319 
03320 void streamerNode::setValidity(bool val) {
03321         if ((val == false) && (configData.verboseMode)) { ROS_INFO("Validity being set to false.."); }
03322         videoValid = val;
03323 }
03324 
03325 streamerSource * streamerNode::getMainVideoSource() {
03326         return mainVideoSource;
03327 }
03328 
03329 cv::VideoCapture * streamerNode::getVideoCapture() {
03330         return &cap;
03331 }
03332 
03333 void streamerNode::updateMap() {
03334         
03335         if (configData.verboseMode) { ROS_INFO("Updating map..."); }
03336         
03337         if (configData.autoAlpha) {
03338                 configData.alpha = findBestAlpha(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalCameraInfo.cameraSize);
03339                 
03340                 if (configData.verboseMode) { ROS_INFO("Optimal alpha: (%f)", configData.alpha); }
03341 
03342         }
03343         
03344         cv::Rect* validPixROI = 0;
03345         globalCameraInfo.newCamMat = getOptimalNewCameraMatrix(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalCameraInfo.cameraSize, configData.alpha, globalCameraInfo.cameraSize, validPixROI, centerPrincipalPoint);
03346         
03347         //HGH initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalCameraInfo.R, globalCameraInfo.newCamMat, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
03348         //HGH
03349         if (configData.wantsToAddExtrinsics){
03350 
03351             //update camera info extrinsics...
03352             getRectification();
03353             updateCameraInfoExtrinsics();
03354 
03355             if (configData.wantsToRectify){
03356                 if (configData.camera_number == 0){
03357                     cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalExtrinsicsData.R0, globalExtrinsicsData.P0, globalCameraInfo.cameraSize, CV_32FC1,  map1, map2);
03358                 }else if (configData.camera_number == 1){
03359                     cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalExtrinsicsData.R1, globalExtrinsicsData.P1, globalCameraInfo.cameraSize, CV_32FC1,  map1, map2);
03360                 }
03361             }else{
03362                 cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs,  cv::Mat(), globalCameraInfo.newCamMat, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
03363             }
03364 
03365         }else{
03366             cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs,  cv::Mat() , globalCameraInfo.newCamMat, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
03367         }
03368 
03369         alphaChanged = false;
03370         
03371         if (configData.verboseMode) { ROS_INFO("Map updated."); }
03372 }
03373 
03374 void streamerNode::serverCallback(thermalvis::streamerConfig &config, uint32_t level) {
03375         
03376         if (configData.verboseMode){ ROS_INFO("Processing reconfigure request..."); }
03377         
03378         //configData.radiometricCorrection = config.radiometricCorrection;
03379         //configData.radiometricRaw = config.radiometricRaw;
03380         configData.minTemperature = config.minTemperature;
03381         configData.maxTemperature = config.maxTemperature;
03382         //configData.radiometricBias = config.radiometricBias;
03383         
03384         //configData.alreadyCorrected = config.alreadyCorrected;
03385         
03386         //configData.stepChangeTempScale = config.stepChangeTempScale;
03387         
03388         if (configData.autoTemperature != config.autoTemperature) {
03389                 lastMinDisplayTemp = -9e99, lastMaxDisplayTemp = 9e99;
03390                 configData.autoTemperature = config.autoTemperature;
03391         }
03392         
03393         
03394         
03395         //configData.smoothThermistor = config.smoothThermistor;
03396         //configData.thermistorWindow = config.thermistorWindow;
03397         
03398         //configData.radiometricInterpolation = config.radiometricInterpolation;
03399         
03400         if (configData.detectorMode != config.detectorMode) {
03401                 
03402                 configData.detectorMode = config.detectorMode;
03403                 
03404                 if (!configData.serialComms) {
03405                         ROS_WARN("Selecting a detector mode has no effect unless serial comms are enabled.");
03406                 } else {
03407                         updateDetectorMode = true;
03408                 }
03409                 
03410                 
03411         }
03412         
03413         
03414         configData.usbMode = config.usbMode;
03415         if (!configData.serialComms) {
03416                 if (configData.usbMode != config.usbMode) {
03417                         ROS_WARN("Selecting a USB mode has no effect unless serial comms are enabled.");
03418                 }
03419         } else {
03420                 
03421                 updateUSBMode = true;
03422                 
03423                 if (configData.usbMode == USB_MODE_16) {
03424                         if (configData.verboseMode) { ROS_INFO("changing <configData.inputDatatype> to DATATYPE_RAW"); }
03425                         config.inputDatatype = DATATYPE_RAW;
03426                         if (configData.outputType != "CV_8UC3") { configData.outputType = "CV_16UC1"; }
03427                 } else if (configData.usbMode == USB_MODE_8) {
03428                         config.inputDatatype = DATATYPE_8BIT;
03429                         if (configData.outputType != "CV_8UC3") { configData.outputType = "CV_8UC1"; }
03430                 }
03431         
03432                 
03433         }
03434         
03435         
03436         
03437         /*
03438         if (configData.readThermistor != config.readThermistor) {
03439                 configData.readThermistor = config.readThermistor;
03440                 
03441                 if (configData.readThermistor) {
03442                         if (configData.verboseMode) { ROS_INFO("Wants to read from thermistor"); }
03443                         //ROS_WARN("Writing thermistor values to (%s)...", thermistorLogFile.c_str());
03444                         //ofs_thermistor_log.open(thermistorLogFile.c_str());
03445                 } else {
03446                         if (ofs_thermistor_log.is_open()) ofs_thermistor_log.close();
03447                         
03448                         // Want system to know that the last reading is invalid..
03449                         lastThermistorReading = -99.0;
03450                 }
03451                 
03452         }
03453         */
03454         
03455         //configData.wantsToMarkDuplicates = config.markDuplicates;
03456         //configData.wantsToOutputDuplicates = config.dumpDuplicates;
03457         
03458         //configData.temporalSmoothing = config.temporalSmoothing;
03459         
03460         //configData.maxThermistorDiff = config.maxThermistorDiff;
03461         
03462         //configData.alternatePeriod = config.alternatePeriod;
03463         
03464         if (configData.serialPollingRate != config.serialPollingRate) {
03465                 configData.serialPollingRate = config.serialPollingRate;
03466                 if (configData.verboseMode) { ROS_INFO("Updating period with rate (%f)", configData.serialPollingRate); }
03467                 
03468                 if (configData.serialPollingRate > 0.1) {
03469                         serial_timer.setPeriod(ros::Duration(1.0 / configData.serialPollingRate));
03470                 } else {
03471                         serial_timer.setPeriod(ros::Duration(1.0 / 1.0));
03472                 }
03473         }
03474         
03475         if (configData.maxNucInterval != config.maxNucInterval) {
03476                 
03477                 configData.maxNucInterval = config.maxNucInterval;
03478                 ROS_WARN("NUC interval changed by config...");
03479                 updateNucInterval = true;
03480         }
03481         
03482         if (configData.maxNucThreshold != config.maxNucThreshold) {
03483                 
03484                 configData.maxNucThreshold = config.maxNucThreshold;
03485                 updateNucInterval = true;
03486         }
03487         
03488         
03489         if (!configData.temporalSmoothing) {
03490                 lastMedian = -1.0;
03491         }
03492         
03493         configData.verboseMode = config.verboseMode;
03494         //configData.displayThermistor = config.displayThermistor;
03495         
03496         //configData.maxIntensityChange = config.maxShift;
03497         //configData.temporalMemory = config.temporalMemory;
03498             
03499         //configData.syncDiff = config.syncDiff;
03500         
03501         
03502         
03503         //configData.loopMode = config.loopMode; 
03504         
03505         configData.normFactor = config.normFactor;
03506 
03507         /*
03508         bool updateWriteParams = false;
03509         if ((configData.writeQuality != config.writeQuality) || (configData.outputFormat != config.outputFormat)) {
03510                 updateWriteParams = true;
03511         }
03512         */
03513         
03514         /*
03515         if (configData.forceInputGray != config.forceInputGray) {
03516                 firstFrame = true;
03517         }
03518         */
03519         
03520         //configData.forceInputGray = config.forceInputGray;
03521         
03522         //configData.fixDudPixels = config.fixDudPixels;
03523         
03524         //configData.writeQuality = config.writeQuality;
03525         
03526         if (config.framerate != 0.0) {
03527                 configData.pauseMode = false;
03528         }
03529         
03530         /*
03531         if ((config.autoAlpha != configData.autoAlpha) || ((!config.autoAlpha) && (config.alpha != configData.alpha))) {
03532   
03533                 configData.autoAlpha = config.autoAlpha;
03534                 configData.alpha = config.alpha;
03535                 
03536                 alphaChanged = true;
03537                 
03538                 
03539                 
03540         } else {
03541 
03542                 //HGH
03543                 if (configData.alpha != config.alpha){
03544                     if (configData.wantsToAddExtrinsics){
03545                         getRectification();
03546                         updateCameraInfoExtrinsics();
03547                     }
03548                 }
03549 
03550                 configData.alpha = config.alpha;
03551         }
03552         */
03553         
03554         if (alphaChanged) {
03555                 if (configData.verboseMode) { ROS_INFO("Updating map..."); }
03556                 updateMap();
03557         }
03558         
03559         fusionFactor = config.fusionFactor;
03560         
03561         //ROS_WARN("Progressing...");
03562             
03563         if (config.framerate < 0.0) {
03564                 
03565                 if (configData.pollMode) {
03566                 
03567                         ROS_WARN("Invalid framerate (%f) so switching to capture mode.", config.framerate);
03568                         configData.framerate = DEFAULT_READ_RATE;
03569                         configData.pollMode = false;
03570                         configData.captureMode = true;
03571                         
03572                 } else if (configData.readMode) {
03573                         
03574                         ROS_WARN("Invalid framerate (%f) so defaulting to (%f).", config.framerate, DEFAULT_READ_RATE);
03575                         configData.framerate = DEFAULT_READ_RATE;
03576 
03577                 } else if (configData.loadMode) {
03578                         
03579                         ROS_WARN("Invalid framerate (%f) so defaulting to (%f).", config.framerate, DEFAULT_READ_RATE);
03580                         configData.framerate = DEFAULT_READ_RATE;
03581                         
03582                 } else if (configData.resampleMode) {
03583                         
03584                         ROS_WARN("Invalid framerate (%f) so switching to subscribe mode.", config.framerate);
03585                         configData.framerate = DEFAULT_READ_RATE;
03586                         configData.resampleMode = false;
03587                         configData.subscribeMode = true;
03588                         
03589                 }
03590 
03591                 timer.setPeriod(ros::Duration(1.0 / DEFAULT_READ_RATE));
03592                 
03593         } else {
03594                 
03595                 if (configData.captureMode) {
03596                 
03597                         ROS_INFO("Specified framerate (%f) so switching to poll mode.", config.framerate);
03598                         configData.framerate = config.framerate;
03599                         configData.captureMode = false;
03600                         configData.pollMode = true;
03601                         
03602                 } else if (configData.subscribeMode) {
03603                         
03604                         ROS_INFO("Specified framerate (%f) so switching to resample mode.", config.framerate);
03605                         configData.framerate = config.framerate;
03606                         configData.subscribeMode = false;
03607                         configData.resampleMode = true;
03608                         
03609                 }
03610                 
03611                 if (config.framerate > 0.0) {
03612                         timer.setPeriod(ros::Duration(1.0 / config.framerate));
03613                 } else {
03614                         configData.pauseMode = true;
03615                         timer.setPeriod(ros::Duration(1.0 / 1.0));
03616                 }
03617                 
03618                 
03619         }
03620         
03621         if (config.inputDatatype != configData.inputDatatype) {
03622                 if (configData.readMode) {
03623                         ROS_WARN("You cannot change the bit-reading mode mid-stream. Consider restarting.");
03624                 } else if ((configData.captureMode) || (configData.pollMode)) {
03625                         if (configData.verboseMode) { ROS_INFO("Resetting device in order to change streaming mode to (%d)...", config.inputDatatype); }
03626                         releaseDevice();
03627                         if (configData.verboseMode) { ROS_INFO("device released..."); }
03628                         configData.inputDatatype = config.inputDatatype;
03629                         if (configData.verboseMode) { ROS_INFO("Changing to (%d)", configData.inputDatatype); }
03630                         setupDevice();
03631                         if (configData.verboseMode) { ROS_INFO("Set up done."); }
03632                 } else {
03633                         configData.inputDatatype = config.inputDatatype;
03634                 }
03635 
03636         }
03637         
03638         //configData.filterMode = config.filterMode;
03639         //configData.filterParam = config.filterParam;
03640         
03641         //configData.maxReadAttempts = config.maxReadAttempts;
03642         
03643         configData.normMode = config.normMode;
03644         
03645         bool wantsToRefreshCameras = false;
03646         
03647         if (config.output16bit && !configData.output16bitFlag) {
03648                 configData.output16bitFlag = true;
03649                 wantsToRefreshCameras = true;
03650         } else if (!config.output16bit && configData.output16bitFlag) {
03651                 configData.output16bitFlag = false;
03652                 wantsToRefreshCameras = true;
03653         }
03654         
03655         if (config.output8bit && !configData.output8bitFlag) {
03656                 configData.output8bitFlag = true;
03657                 wantsToRefreshCameras = true;
03658         } else if (!config.output8bit && configData.output8bitFlag){
03659                 configData.output8bitFlag = false;
03660                 wantsToRefreshCameras = true;
03661         }
03662         
03663         if (config.outputColor && !configData.outputColorFlag) {
03664                 configData.outputColorFlag = true;
03665                 wantsToRefreshCameras = true;
03666         } else if (!config.outputColor && configData.outputColorFlag) {
03667                 configData.outputColorFlag = false;
03668                 wantsToRefreshCameras = true;
03669         }
03670         
03671         if (wantsToRefreshCameras) {
03672                 refreshCameraAdvertisements();
03673         }
03674             
03675         getMapping(config.map, configData.extremes, configData.mapCode, configData.mapParam);
03676         colourMap.load_standard(configData.mapCode, configData.mapParam);
03677     
03678         if (configData.outputFolder != "outputFolder") {
03679                 
03680                 /*
03681                 if (config.writeImages) {
03682                         
03683                         if (configData.wantsToWrite != config.writeImages) {
03684                         
03685                                 // Create folders if necessary
03686                                 struct stat st;
03687                                 if(stat(configData.outputFolder.c_str(),&st) != 0) {
03688                                         char folderCommand[256];
03689                                         sprintf(folderCommand, "mkdir -p %s", configData.outputFolder.c_str());
03690                                         int res = system(folderCommand);
03691                                         
03692                                         if (res == 0) {
03693                                                 ROS_WARN("system() call returned 0...");
03694                                         }
03695                                 }
03696                                 
03697                         }
03698                         
03699                 }
03700                 
03701                 configData.wantsToWrite = config.writeImages;
03702                 */
03703                 
03704                 /*
03705                 if (configData.wantsToDumpTimestamps != config.dumpTimestamps) {
03706                         
03707                         if (configData.wantsToDumpTimestamps) {
03708                                 ofs.open(configData.outputTimeFile.c_str(), fstream::ate);
03709                         } else {
03710                                 ofs.close();
03711                         }
03712                         
03713                 }
03714                         
03715                 configData.wantsToDumpTimestamps = config.dumpTimestamps;
03716                 */
03717                 
03718         } else {
03719                 ROS_WARN("No valid output folder specified...");
03720                 configData.wantsToWrite = false;
03721                 configData.wantsToDumpTimestamps = false;
03722         }
03723         
03724        //HGH
03725         //configData.wantsToRectify = config.rectifyImages;
03726 
03727         if (config.undistortImages) {
03728                 //if (map1.rows == 0) {
03729                     //HGH  initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalCameraInfo.R, globalCameraInfo.newCamMat, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
03730                     //HGH
03731                     if (configData.wantsToAddExtrinsics){
03732                         if (configData.wantsToRectify){
03733                             if (configData.camera_number == 0){
03734                                 cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalExtrinsicsData.R0, globalExtrinsicsData.P0, globalCameraInfo.cameraSize, CV_32FC1,  map1, map2);
03735                             }else if (configData.camera_number == 1){
03736                                 cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalExtrinsicsData.R1, globalExtrinsicsData.P1, globalCameraInfo.cameraSize, CV_32FC1,  map1, map2);
03737                             }
03738                             //initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs, globalCameraInfo.R, globalCameraInfo.newCamMat, globalCameraInfo.cameraSize, CV_16SC2/*CV_32FC1*/, map1, map2);
03739                         }else{
03740                             cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs,  cv::Mat(), globalCameraInfo.newCamMat, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
03741                         }
03742                     }else{
03743                         cv::initUndistortRectifyMap(globalCameraInfo.cameraMatrix, globalCameraInfo.distCoeffs,  cv::Mat(), globalCameraInfo.newCamMat, globalCameraInfo.cameraSize, CV_32FC1, map1, map2);
03744                     }
03745                   //  }
03746         }       
03747 
03748         configData.wantsToUndistort = config.undistortImages;
03749         
03750         //configData.wantsToRemoveDuplicates = config.removeDuplicates;
03751         
03752         //configData.outputFormat = config.outputFormat;
03753         
03754         //ROS_ERROR("configData.outputFormat = %d", configData.outputFormat);
03755         
03756         /*
03757         if (configData.outputFormat == 0) {
03758                 configData.outputFormatString = "jpg";
03759         } else if (configData.outputFormat == 1) {
03760                 configData.outputFormatString = "pgm";
03761         } else if (configData.outputFormat == 2) {
03762                 configData.outputFormatString = "bmp";
03763         } else if (configData.outputFormat == 3) {
03764                 configData.outputFormatString = "ppm";
03765         } else if (configData.outputFormat == 4) {
03766                 configData.outputFormatString = "png";
03767         }
03768         */
03769         
03770         //ROS_ERROR("configData.outputFormatString = %s", configData.outputFormatString.c_str());
03771         
03772         /*
03773         if (config.outputType == 0) {
03774                 configData.outputType = "CV_8UC1";
03775         } else if (config.outputType == 1) {
03776                 configData.outputType = "CV_8UC3";
03777                 if (configData.outputFormatString == "pgm") {
03778                         ROS_WARN("PGM cannot write as CV_8UC3...");
03779                 }
03780         } else if (config.outputType == 2) {
03781                 configData.outputType = "CV_16UC1";
03782                 if ((configData.outputFormatString == "jpg") || (configData.outputFormatString == "bmp")) {
03783                         ROS_WARN("JPG/BMP cannot write as CV_16UC1...");
03784                 }
03785         }
03786         */
03787         
03788         if (!firstServerCallbackProcessed) {
03789                 firstServerCallbackProcessed = true;
03790         }
03791         
03792         if (configData.verboseMode) { ROS_INFO("Reconfigure request complete..."); }
03793 }
03794         
03795 int getMapIndex(string mapping) {
03796         
03797         int map;
03798         
03799         if (mapping == "GRAYSCALE") {
03800                 map = 0;
03801         } else if (mapping == "CIECOMP") {
03802                 map = 1;
03803         } else if (mapping == "BLACKBODY") {
03804                 map = 2;
03805         } else if (mapping == "RAINBOW") {
03806                 map = 3;
03807         } else if (mapping == "IRON") {
03808                 map = 4;
03809         } else if (mapping == "BLUERED") {
03810                 map = 5;
03811         } else if (mapping == "JET") {
03812                 map = 6;
03813         } else if (mapping == "CIELUV") {
03814                 map = 7;
03815         } else if (mapping == "ICEIRON") {
03816                 map = 8;
03817         } else if (mapping == "ICEFIRE") {
03818                 map = 9;
03819         } else if (mapping == "REPEATED") {
03820                 map = 10;
03821         } else if (mapping == "HIGHLIGHTED") {
03822                 map = 11;
03823         } else {
03824                 map = 0;
03825         }
03826         
03827         return map;
03828 }
03829 
03830 /*
03831 int streamerNode::mygetch() {
03832   struct termios oldt,newt;
03833   int ch;
03834   tcgetattr( STDIN_FILENO, &oldt );
03835   newt = oldt;
03836   newt.c_lflag &= ~( ICANON | ECHO );
03837   tcsetattr( STDIN_FILENO, TCSANOW, &newt );
03838   ch = getchar();
03839   tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
03840   return ch;
03841 }
03842 */
03843 
03844 void set_blocking (int fd, int should_block)
03845 {
03846         struct termios tty;
03847         memset (&tty, 0, sizeof tty);
03848         if (tcgetattr (fd, &tty) != 0)
03849         {
03850                         ROS_ERROR("error %d getting term settings set_blocking", errno);
03851                         //return;
03852         }
03853 
03854         tty.c_cc[VMIN]  = should_block ? 1 : 0;
03855         tty.c_cc[VTIME] = should_block ? 5 : 0; // 0.5 seconds read timeout
03856 
03857         if (tcsetattr (fd, TCSANOW, &tty) != 0)
03858                 ROS_ERROR("error setting term %sblocking", should_block ? "" : "no");
03859 }
03860 
03861 int streamerNode::open_port() {
03862    int fd;                                   /* File descriptor for the port */
03863 
03864 
03865    //fd = open(configData.portAddress.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
03866    //fd = open(configData.portAddress.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK); 
03867    //fd = open(configData.portAddress.c_str(), O_RDWR | O_NOCTTY | O_SYNC);
03868    fd = open(configData.portAddress.c_str(), O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK | O_SYNC);
03869    
03870    set_blocking (fd, 0);   // disable reads blocked when no input ready
03871 
03872         char buf [10000];
03873         int n;
03874         do {
03875                         n = read (fd, buf, sizeof buf);
03876         } while (n > 0);
03877 
03878         //set_blocking (fd, 1);  // enable read blocking (if desired)
03879    
03880    usleep(200000);
03881    tcflush(fd, TCIOFLUSH);
03882 
03883    if (fd == -1) {                                              /* Could not open the port */
03884      ROS_ERROR("open_port(): Unable to open (%s) (%s)", configData.portAddress.c_str(), strerror(errno));
03885    } else {
03886            //ROS_ERROR("port (%s) opened", configData.portAddress.c_str());
03887            //fcntl(fd, F_SETFL, 0);
03888            
03889    }
03890    return (fd);
03891 }
03892  
03893 void displayTermiosData(termios options) {
03894         
03895         ROS_INFO("   Termios Summary:");
03896         
03897         ROS_INFO("c_iflag = (%d)", options.c_iflag);
03898         ROS_INFO("c_oflag = (%d)", options.c_oflag);
03899         ROS_INFO("c_cflag = (%d)", options.c_cflag);
03900         ROS_INFO("c_lflag = (%d)", options.c_lflag);
03901         ROS_INFO("c_ispeed = (%d)", options.c_ispeed);
03902         ROS_INFO("c_ospeed = (%d)", options.c_ospeed);
03903         
03904         for (unsigned int iii = 0; iii < NCCS; iii++) {
03905                 ROS_INFO("c_cc[%d] = (%d)", iii, options.c_cc[iii]);
03906         }
03907         
03908         ROS_WARN("Termios Summary Complete.");
03909         
03910         /*
03911         tcflag_t c_iflag;
03912         tcflag_t c_oflag;
03913         tcflag_t c_cflag;
03914         tcflag_t c_lflag;
03915         cc_t c_cc[NCCS];
03916         speed_t c_ispeed;
03917         speed_t c_ospeed
03918         */
03919         
03920 }
03921  
03922 bool streamerNode::configureSerialComms() {
03923         
03924         
03925         struct termios options;
03926    
03927         mainfd = open_port();
03928         
03929         //sleep(2); //required to make flush work, for some reason
03930         //tcflush(mainfd,TCIOFLUSH);
03931         
03932         int fcntl_ret = fcntl(mainfd, F_SETFL, FNDELAY); /* Configure port reading */
03933         //int fcntl_ret = fcntl(mainfd, F_SETFL, 0);
03934         
03935         if (fcntl_ret != 0) { ROS_ERROR("fcntl_ret = (%d)", fcntl_ret); }
03936         
03937         //sleep(2); //required to make flush work, for some reason
03938         //tcflush(mainfd,TCIOFLUSH);
03939         
03940         if (configData.verboseMode) { displayTermiosData(options); }
03941         
03942         //int tcgetattr_ret = tcgetattr(mainfd, &options);                                      /* Get the current options for the port */
03943         //ROS_ERROR("tcgetattr_ret = (%d)", tcgetattr_ret);
03944         
03945         if (0) { // Attempt to write with 1-1 converter
03946                 
03947         bzero(&options, sizeof(options));
03948         options.c_cflag = B115200 | CRTSCTS | CS8 | CLOCAL | CREAD; // cflag is common flag?
03949         options.c_iflag = IGNPAR;
03950         options.c_oflag = 0;
03951         
03952         /* set input mode (non-canonical, no echo,...) */
03953         options.c_lflag = 0;
03954          
03955         options.c_cc[VTIME]    = 0;   /* inter-character timer unused */
03956         options.c_cc[VMIN]     = 11;   /* blocking read until 5 chars received */
03957         
03958         tcflush(mainfd, TCIFLUSH);
03959         tcsetattr(mainfd,TCSANOW,&options);
03960         tcflush(mainfd, TCIFLUSH);
03961         } else {
03962                 // Works for the Serial Hub, and writes properly with 1-1 converter
03963                 
03964                 //bzero(&options, sizeof(options));
03965                 
03966                 //options.c_cflag &= B115200;
03967                 
03968                 int cfsetispeed_ret = cfsetispeed(&options, B115200); /* Set the baud rates to 115200 */ // can change "i" to 2400 and it still works, not so with "o" ...
03969                 if (cfsetispeed_ret != 0) { ROS_ERROR("cfsetispeed_ret = (%d)", cfsetispeed_ret); }
03970                 int cfsetospeed_ret = cfsetospeed(&options, B115200);
03971                 if (cfsetospeed_ret != 0) { ROS_ERROR("cfsetospeed_ret = (%d)", cfsetospeed_ret); }
03972                 
03973                 
03974                 
03975                 // should have 1 stop bit, 115200 baud, 8 bits, no parity, no flow control
03976                 
03977                                                                            /* Enable the receiver and set local mode */
03978             
03979                 
03980         
03981                 
03982                 // Hack: additional settings to align with GTKTERM:
03983                 
03984                 if (configData.serialCommsConfigurationCode == SERIAL_COMMS_CONFIG_DEFAULT) {
03985                         
03986                         //ROS_ERROR("Assigning here...");
03987                         
03988                         if (1) {
03989                                 
03990                                 bzero(&options, sizeof(options));
03991                                 
03992                                 options.c_iflag = 0;
03993                                 options.c_oflag = 0;
03994                                 options.c_cflag = 0;
03995                                 options.c_lflag = 0;
03996                                 
03997                                 // http://man7.org/linux/man-pages/man3/termios.3.html
03998                                 
03999                                 //options.c_cflag &= B115200;
04000                                 
04001                                 cfsetispeed(&options, B115200);
04002                                 cfsetospeed(&options, B115200);
04003                 
04004                                 //int cfsetispeed_ret = cfsetispeed(&options, B115200); /* Set the baud rates to 115200 */ // can change "i" to 2400 and it still works, not so with "o" ...
04005                                 //ROS_ERROR("cfsetispeed_ret = (%d)", cfsetispeed_ret);
04006                                 //int cfsetospeed_ret = cfsetospeed(&options, B115200);
04007                                 //ROS_ERROR("cfsetospeed_ret = (%d)", cfsetospeed_ret);
04008                                 
04009                                 
04010                                 
04011                                 // c_iflag : http://www.delorie.com/gnu/docs/glibc/libc_362.html
04012                                 options.c_iflag &= ~INPCK;
04013                                 options.c_iflag |= IGNPAR;
04014                                 options.c_iflag &= ~PARMRK;
04015                                 options.c_iflag &= ~ISTRIP;
04016                                 options.c_iflag |= IGNBRK;
04017                                 options.c_iflag &= ~BRKINT;
04018                                 options.c_iflag &= ~IGNCR;
04019                                 options.c_iflag &= ~ICRNL;
04020                                 options.c_iflag &= ~INLCR;
04021                                 options.c_iflag &= ~IXOFF;
04022                                 options.c_iflag &= ~IXON;
04023                                 options.c_iflag &= ~IXANY;
04024                                 options.c_iflag &= ~IMAXBEL;
04025                                 // UNUSED:
04026                                 options.c_iflag &= ~IUCLC;
04027                                 options.c_iflag &= ~IUTF8;
04028                                 
04029                                 
04030                                 // c_oflag : http://www.delorie.com/gnu/docs/glibc/libc_363.html
04031                                 options.c_oflag &= ~OPOST;
04032                                 options.c_oflag &= ~ONLCR;
04033                                 // UNUSED: oxtabs, onoeot
04034                                 options.c_oflag &= ~OLCUC;
04035                                 options.c_oflag &= ~OCRNL;
04036                                 options.c_oflag &= ~ONOCR;
04037                                 options.c_oflag &= ~ONLRET;
04038                                 options.c_oflag &= ~OFILL;
04039                                 options.c_oflag &= ~OFDEL;
04040                                 
04041                                 options.c_oflag |= NL0;
04042                                 options.c_oflag |= CR0;
04043                                 options.c_oflag |= TAB0;
04044                                 options.c_oflag |= BS0;
04045                                 options.c_oflag |= VT0;
04046                                 options.c_oflag |= FF0;
04047                                 
04048                                 
04049                                 // c_cflag : http://www.delorie.com/gnu/docs/glibc/libc_364.html
04050                                 options.c_cflag |= CLOCAL;
04051                                 options.c_cflag &= ~HUPCL;
04052                                 options.c_cflag |= CREAD;
04053                                 options.c_cflag &= ~CSTOPB; 
04054                                 options.c_cflag &= ~PARENB;
04055                                 options.c_cflag &= ~PARODD;
04056                                 options.c_cflag &= ~CSIZE;
04057                                 options.c_cflag |= CS8;
04058                                 // UNUSED: cs5, cs6, cs7, ccts_oflow, crts_iflow, mdmbuf, cignore
04059                                 //options.c_cflag &= ~CRTSCTS;
04060                                 options.c_cflag &= ~CRTSCTS;
04061                                 
04062                                 
04063                                 // c_lflag : http://www.delorie.com/gnu/docs/glibc/libc_365.html
04064                                 options.c_lflag &= ~ICANON;
04065                                 options.c_lflag &= ~ECHO;
04066                                 options.c_lflag &= ~ECHOE;
04067                                 options.c_lflag &= ~ECHOPRT;
04068                                 options.c_lflag &= ~ECHOK;
04069                                 options.c_lflag &= ~ECHOKE;
04070                                 options.c_lflag &= ~ECHONL;
04071                                 options.c_lflag &= ~ECHOCTL;
04072                                 options.c_lflag &= ~ISIG;
04073                                 options.c_lflag &= ~IEXTEN;
04074                                 options.c_lflag &= ~NOFLSH;
04075                                 options.c_lflag &= ~TOSTOP;
04076                                 // UNUSED: altwerase, flusho, nokerninfo, pendin
04077                                 options.c_lflag &= ~XCASE;              
04078                                 
04079                                 options.c_ispeed = B115200;
04080                                 options.c_ospeed = B115200;
04081                                 
04082                                 
04083                                 options.c_cc[0] = 79;
04084                                 options.c_cc[1] = 215;
04085                                 options.c_cc[2] = 212;
04086                                 options.c_cc[3] = 255;
04087                                 options.c_cc[4] = 127;
04088                                 
04089                                 options.c_cc[5] = 0;
04090                                 options.c_cc[6] = 0;
04091                                 options.c_cc[7] = 88;
04092                                 options.c_cc[8] = 42;
04093                                 options.c_cc[9] = 121;
04094                                 
04095                                 options.c_cc[10] = 106;
04096                                 options.c_cc[11] = 96;
04097                                 options.c_cc[12] = 127;
04098                                 options.c_cc[13] = 0;
04099                                 options.c_cc[14] = 0;
04100                                 
04101                                 options.c_cc[15] = 104;
04102                                 options.c_cc[16] = 41;
04103                                 options.c_cc[17] = 121;
04104                                 options.c_cc[18] = 106;
04105                                 options.c_cc[19] = 96;
04106                                 
04107                                 options.c_cc[20] = 127;
04108                                 options.c_cc[21] = 0;
04109                                 options.c_cc[22] = 0;
04110                                 options.c_cc[23] = 16;
04111                                 options.c_cc[24] = 16;
04112                                 
04113                                 options.c_cc[25] = 121;
04114                                 options.c_cc[26] = 106;
04115                                 options.c_cc[27] = 96;
04116                                 options.c_cc[28] = 127;
04117                                 options.c_cc[29] = 0;
04118                                 
04119                                 options.c_cc[30] = 0;
04120                                 options.c_cc[31] = 144;
04121                                 
04122                                 
04123                                 //options.c_cc[VTIME]    = 0;   /* inter-character timer unused */
04124                                 //options.c_cc[VMIN]     = 1;   /* blocking read until 1 char received */
04125 
04126                                 tcflush(mainfd, TCOFLUSH );
04127                                 tcflush(mainfd, TCIFLUSH);
04128                                 
04129                                 int yes = 1;
04130                                 
04131                                 ioctl(mainfd, TIOCCONS, &yes);
04132                                 
04133                                 // Taken from : http://tldp.org/HOWTO/Serial-Programming-HOWTO/x115.html
04134                                                 
04135                         } else {
04136                                 
04137                                 //ROS_ERROR("Old ones...");
04138                                 
04139                                 options.c_cflag |= (CLOCAL | CREAD);
04140                                 options.c_cflag &= ~PARENB; /* Mask the character size to 8 bits, no parity */ // changed to PARENB (no effect in streamer)
04141                                 options.c_cflag |= CSTOPB;
04142                                 options.c_cflag &= ~CSIZE;
04143                                 options.c_cflag |=  CS8; /* Select 8 data bits */ // changing to 7 breaks...
04144                                 options.c_cflag &= ~CRTSCTS; /* Disable hardware flow control */  
04145                                 
04146                                 // Try to set some of these...
04147                                 options.c_oflag = 0;
04148                          
04149                                                                                          /* Enable data to be processed as raw input */
04150                                 options.c_lflag &= ~(ICANON | ECHO | ISIG);
04151                                 //options.c_lflag = 0;
04152                                 
04153                                 options.c_cflag &= ~CSTOPB;
04154                                 options.c_cflag &= ~HUPCL;
04155                                 
04156                                 
04157                                 options.c_cflag &= IGNBRK;
04158                                 options.c_cflag &= IGNPAR;      
04159                                 //options.c_cflag |= IGNBRK;
04160                                 //options.c_cflag |= IGNPAR;    
04161                                 
04162                                 options.c_cflag &= ~ICRNL;
04163                                 options.c_cflag &= ~IXON;
04164                                 options.c_cflag &= ~IEXTEN;
04165                                 options.c_cflag &= ~ECHOE;
04166                                 options.c_cflag &= ~ECHOK;
04167                                 options.c_cflag &= ~ECHOCTL;
04168                                 options.c_cflag &= ~ECHOKE;
04169                                 
04170                                 
04171                         }
04172                         
04173 
04174                         
04175                                         
04176                 } else {
04177                         if (configData.verboseMode) { ROS_INFO("Using modified serial comms configuration settings..."); }
04178                 }
04179                 
04180                 if (configData.verboseMode) { displayTermiosData(options); }
04181                    
04182                 /* Set the new options for the port */
04183                 //int tcsetattr_ret = tcsetattr(mainfd, TCSAFLUSH, &options);
04184                 int tcsetattr_ret = tcsetattr(mainfd, TCSANOW, &options);
04185                 
04186                 
04187                 if (tcsetattr_ret != 0) { ROS_ERROR("tcsetattr_ret = (%d)", tcsetattr_ret); }
04188                 
04189                 //tcsetattr(mainfd, TCSAFLUSH, &options);
04190                 //sleep(2); //required to make flush work, for some reason
04191                 tcflush(mainfd,TCIOFLUSH);
04192                 
04193         }
04194         
04195         
04196         
04197         
04198         
04199         {
04200                 if (configData.verboseMode) { ROS_INFO("SerialComms: Opening shutter..."); }
04201                 char localCommand[256];
04202                 sprintf(localCommand, "open");
04203                 if (!sendSerialCommand(localCommand, configData.serialWriteAttempts)) ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, configData.serialWriteAttempts);
04204         }
04205         
04206         {
04207                 // Trying to clear serial comms buffer...
04208                 int n;
04209                 char buff[SERIAL_BUFF_SIZE];    
04210                 n = read(mainfd, buff, SERIAL_BUFF_SIZE);
04211                 
04212                 if (configData.verboseMode) { ROS_INFO("Cleared (%d) characters from buffer: (%s)", n, buff); }
04213                 
04214         }
04215         
04216         int statusNum = 0;
04217         
04218         
04219         
04220         if (configData.disableSkimming) {
04221                 // Check current SKIMACTIVE status
04222                 char localCommand[256];
04223                 sprintf(localCommand, "SKIMACTIVE");
04224                 
04225                 if (1) { ROS_INFO("SerialComms: Disabling mean-shifting..."); }
04226                 if (!sendSerialCommand(localCommand, 1)) ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, 1);
04227                 
04228                 ros::Duration(1.0).sleep();
04229                 
04230                 char buff[SERIAL_BUFF_SIZE];    
04231                 read(mainfd, buff, SERIAL_BUFF_SIZE);
04232                 //ROS_WARN("Message received = (%s)\n", buff);
04233                 //printf("%s\n", buff);
04234                 
04235                 //istringstream ss_buff( &buff[103]);
04236                 
04237                 statusNum = atof(&buff[17]);
04238                 if (configData.verboseMode) { ROS_INFO("SKIMACTIVE status = (%d)", statusNum); }
04239                 
04240         }
04241         
04242         ros::Duration(1.0).sleep();
04243                                         
04244         if (configData.disableSkimming) {
04245                 char localCommand[256];
04246                 sprintf(localCommand, "SKIMACTIVE 0");
04247                 
04248                 if (configData.verboseMode) { ROS_INFO("SerialComms: Verifying disabling of mean-shifting..."); }
04249                 if (!sendSerialCommand(localCommand, 1)) ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, 1);
04250 
04251         }
04252         
04253         {
04254                 char localCommand[256];
04255                 sprintf(localCommand, "SAVE");
04256                 
04257                 if (configData.verboseMode) { ROS_INFO("SerialComms: Saving current settings..."); }
04258                 if (!sendSerialCommand(localCommand, 1)) ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, 1);
04259                 
04260                 
04261         }
04262         
04263         int n;
04264         char buff[SERIAL_BUFF_SIZE];
04265         
04266         n = read(mainfd, buff, SERIAL_BUFF_SIZE);
04267         
04268         // if has 5 characters, is probably just " DSP:> "
04269         if ((configData.verboseMode) && (n != 0)) { ROS_WARN("read(): n = (%d)", n); }
04270         
04271         sleep(2); //required to make flush work, for some reason
04272         tcflush(mainfd,TCIOFLUSH);
04273 
04274         //ROS_WARN("Attempting initial reading of thermistor, 1 failure is expected..");
04275         // getThermistorReading();
04276         
04277         //sleep(2); //required to make flush work, for some reason
04278         //tcflush(mainfd,TCIOFLUSH);
04279         
04280         //sleep(2); //required to make flush work, for some reason
04281         // tcflush(mainfd,TCIOFLUSH);
04282         
04283         // Ensure shutter is open...
04284         
04285         //n = read(mainfd, buff, SERIAL_BUFF_SIZE);
04286         
04287         //sleep(2); //required to make flush work, for some reason
04288         //tcflush(mainfd,TCIOFLUSH);
04289         
04290         //getThermistorReading();
04291         
04292         //sleep(2); //required to make flush work, for some reason
04293         //tcflush(mainfd,TCIOFLUSH);
04294         
04295         // Ensure shutter is open...
04296         
04297         //n = read(mainfd, buff, SERIAL_BUFF_SIZE);
04298         
04299         if (configData.disableSkimming) {
04300                 if (statusNum == 1) {
04301                         ROS_ERROR("Camera must now be powercycled: SKIMACTIVE was not originally off.");
04302                         return false;
04303                 } else {
04304                         ROS_WARN("Assuming camera has been powercycled since SKIMACTIVE was saved as off.");
04305                         return true;
04306                 }               
04307         } else {
04308                 return true;
04309         }
04310 
04311 }
04312 
04313 double streamerNode::smoothThermistorReading() {
04314         
04315         int history = min((int)recordedThermistorReadings, MAX_THERMISTOR_READINGS_TO_STORE);
04316         
04317         double smoothedTemperature = 0.0;
04318         
04319         double x[MAX_THERMISTOR_READINGS_TO_STORE], y[MAX_THERMISTOR_READINGS_TO_STORE];
04320         
04321         unsigned int termsToConsider = 0;
04322         
04323         for (int iii = 0; iii < history; iii++) {
04324                 
04325                 if ( ( ros::Time::now().toSec() - thermistorBuffer[(recordedThermistorReadings-iii-1) % MAX_THERMISTOR_READINGS_TO_STORE][0] ) < configData.thermistorWindow) {
04326                         x[termsToConsider] = thermistorBuffer[(recordedThermistorReadings-iii-1) % MAX_THERMISTOR_READINGS_TO_STORE][0];
04327                         y[termsToConsider] = thermistorBuffer[(recordedThermistorReadings-iii-1) % MAX_THERMISTOR_READINGS_TO_STORE][1];
04328                         termsToConsider++;
04329                 }
04330         }
04331         
04332         // Simple average:
04333         if (0) {
04334                 for (unsigned int iii = 0; iii < termsToConsider; iii++) {
04335                         //ROS_INFO("Considering reading (%f, %f)...", x[iii], y[iii]);
04336                         smoothedTemperature += y[iii];
04337                 }
04338                 
04339                 smoothedTemperature /= double(termsToConsider);
04340         }
04341         
04342         //ROS_INFO("termsToConsider = (%d), (%f, %f)", termsToConsider, x[0], y[0]);
04343         
04344         // Linear Regression
04345         if (1) {
04346                 double m, c;
04347                 
04348                 findLinearModel(x, y, termsToConsider, m, c);
04349                 
04350                 // Use the latest
04351                 smoothedTemperature = m * thermistorBuffer[(recordedThermistorReadings-1) % MAX_THERMISTOR_READINGS_TO_STORE][0] + c;
04352                 
04353         }
04354         
04355         //ROS_INFO("smoothedTemperature = (%f)", smoothedTemperature);
04356         
04357         return smoothedTemperature;
04358 }
04359 
04360 bool streamerNode::getNucSettingsReading(int& delay, double& diff) {
04361         
04362         bool writeSucceeded = false;
04363         
04364         char localCommand[256];
04365         sprintf(localCommand, "NUCSET");
04366         if (!sendSerialCommand(localCommand, configData.serialWriteAttempts)) ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, configData.serialWriteAttempts);
04367         
04368         char buff[SERIAL_BUFF_SIZE];
04369         
04370         memset(&buff[0], 0, sizeof(buff));
04371         
04372         int n = read(mainfd, buff, SERIAL_BUFF_SIZE);
04373         
04374         
04375         bool readSucceeded = false;
04376         
04377         //ROS_INFO("read size = (%d)", n);
04378         
04379         if (n < 0) {
04380                 ROS_WARN("NUC settings were unable to be read!");
04381         } else if (n == 0) {
04382                 ROS_WARN("0 characters from NUC settings...");
04383         } else {
04384                 readSucceeded = true;
04385                 
04386         }
04387         
04388         ROS_INFO("Read: (%s)", buff);
04389         
04390         return (writeSucceeded && readSucceeded);
04391         
04392 }
04393 
04394 float streamerNode::getThermistorReading() {
04395         
04396         double retVal;
04397         
04398         bool writeSucceeded = false;
04399         
04400         char localCommand[256];
04401         sprintf(localCommand, "THERM");
04402         if (!sendSerialCommand(localCommand, configData.serialWriteAttempts)) {
04403                 if (configData.verboseMode) { ROS_WARN("Serial command (%s) failed after (%d) attempts", localCommand, configData.serialWriteAttempts); }
04404                 return -9e99;
04405         }
04406         
04407         char buff[SERIAL_BUFF_SIZE];
04408         memset(&buff[0], 0, sizeof(buff));
04409         
04410         int n = read(mainfd, buff, SERIAL_BUFF_SIZE);
04411         
04412         //n = fread(buff, 1, 256, mainfd);
04413         
04414         bool readSucceeded = false;
04415         
04416         //ROS_INFO("read size = (%d)", n);
04417         
04418         if (n < 0) {
04419                 ROS_WARN("Thermistor value was unable to be read!");
04420         } else if (n == 0) {
04421                 ROS_WARN("Zero characters returned from attempted thermistor reading.");
04422         } else {
04423                 readSucceeded = true;
04424         }
04425         
04426         if (!readSucceeded) {
04427                 return -9e99;
04428         }
04429         
04430         for (unsigned int iii = 0; iii < 512; iii++) {
04431                 if (buff[iii] == '\r') {
04432                         buff[iii] = '-';
04433                 }
04434         }
04435         
04436         //ROS_ERROR("getThermistorReading(): Line = [%d] (%s)", n, buff);
04437         
04438         //istringstream ss_buff( &buff[101]); // used to be 103
04439         
04440         retVal = atof(&buff[103]);
04441         
04442         /*
04443         char arrayChar[11];
04444         
04445         for (unsigned int iii = 0; iii < 10; iii++) {
04446                 arrayChar[iii] = buff[100+iii];
04447         }
04448         
04449         arrayChar[10] = '\0';
04450         */
04451         
04452         // if (1) /*(configData.verboseMode)*/ { ROS_INFO("Temperature = (%f), (%s)", retVal, arrayChar); }
04453         
04454         return retVal;
04455         
04456 }


thermalvis
Author(s): Stephen Vidas
autogenerated on Sun Jan 5 2014 11:38:45